No description
Find a file
Xe Iaso e69fadddf1
fix(web/fast): remove event loop thrashing (#880)
Fixes #877

Continued from #879, event loop thrashing can cause stack space
exhaustion on ia32 systems. Previously this would thrash the event loop
in Firefox and Firefox derived browsers such as Pale Moon. I suspect
that this is the ultimate root cause of the bizarre irreproducible bugs
that Pale Moon (and maybe Cromite) users have been reporting since at
least #87 was merged.

The root cause is an invalid boolean statement:

```js
// send a progress update every 1024 iterations. since each thread checks
// separate values, one simple way to do this is by bit masking the
// nonce for multiples of 1024. unfortunately, if the number of threads
// is not prime, only some of the threads will be sending the status
// update and they will get behind the others. this is slightly more
// complicated but ensures an even distribution between threads.
if (
  (nonce > oldNonce) | 1023 && // we've wrapped past 1024
  (nonce >> 10) % threads === threadId // and it's our turn
) {
  postMessage(nonce);
}
```

The logic here looks fine but is subtly wrong as was reported in #877
by a user in the Pale Moon community. Consider the following scenario:

`nonce` is a counter that increments by the worker count every loop.
This is intended to spread the load between CPU cores as such:

| Iteration | Worker ID | Nonce |
| :-------- | :-------- | :---- |
| 1         | 0         | 0     |
| 1         | 1         | 1     |
| 2         | 0         | 2     |
| 3         | 1         | 3     |

And so on.

The incorrect part of this is the boolean logic, specifically the part
with the bitwise or `|`. I think the intent was to use a logical or
(`||`), but this had the effect of making the `postMessage` handler fire
on every iteration. The intent of this snippet (as the comment clearly
indicates) is to make sure that the main event loop is only updated with
the worker status every 1024 iterations per worker. This had the
opposite effect, causing a lot of messages to be sent from workers to
the parent JavaScript context.

This is bad for the event loop.

Instead, I have ripped out that statement and replaced it with a much
simpler increment only counter that fires every 1024 iterations.
Additionally, only the first thread communicates back to the parent
process. This does mean that in theory the other workers could be ahead
of the first thread (posting a message out of a worker has a nonzero
cost), but in practice I don't think this will be as much of an issue as
the current behaviour is.

The root cause of the stack exhaustion is likely the pressure caused by
all of the postMessage futures piling up. Maybe the larger stack size in
64 bit environments is causing this to be fine there, maybe it's some
combination of newer hardware in 64 bit systems making this not be as
much of a problem due to it being able to handle events fast enough to
keep up with the pressure.

Either way, thanks much to @wolfbeast and the Pale Moon community for
finding this. This will make Anubis faster for everyone!

Signed-off-by: Xe Iaso <xe.iaso@techaro.lol>
2025-07-21 18:05:24 -04:00
.devcontainer chore: fix name of backoff-retry, expose in devcontainer 2025-07-18 17:51:13 +00:00
.github build(deps): bump the github-actions group with 2 updates (#871) 2025-07-20 20:54:50 -04:00
.vscode feat: dev container support (#734) 2025-06-29 23:41:29 -04:00
cmd fix(cmd/anubis): add signal handling to metrics server (#856) 2025-07-18 13:56:52 +00:00
data Add services folder, add Uptime Robot policy definition (#838) 2025-07-16 09:17:48 -04:00
decaymap feat(lib): use new challenge creation flow (#749) 2025-07-04 20:42:28 +00:00
docs fix(web/fast): remove event loop thrashing (#880) 2025-07-21 18:05:24 -04:00
internal feat(anubis): add /healthz route to metrics server (#843) 2025-07-17 00:31:18 +00:00
lib Remove duplicated string in Filipino language file (#875) 2025-07-20 23:17:48 -04:00
run fix(run/anubis@.service): unique runtimedir per instance (#750) 2025-07-03 10:29:05 +00:00
test chore: fix name of backoff-retry, expose in devcontainer 2025-07-18 17:51:13 +00:00
utils/cmd/backoff-retry test(ssh-ci): deflake SSH CI with exponential backoff (#859) 2025-07-18 17:46:49 +00:00
var initial import from /x/ monorepo 2025-03-17 19:33:07 -04:00
web fix(web/fast): remove event loop thrashing (#880) 2025-07-21 18:05:24 -04:00
xess chore: Remove unused/dead code (#703) 2025-06-25 09:31:33 -04:00
.air.toml feat: add a strip-base-prefix option (#655) 2025-06-12 17:46:08 -04:00
.gitattributes fix(gitattributes): update pattern for generated files (#652) 2025-06-11 21:00:37 +00:00
.gitignore feat: implement localization system (#716) 2025-06-27 17:49:15 +00:00
.ko.yaml Try using ko to build images 2025-03-19 09:10:29 -04:00
anubis.go feat(localization): Add option for forcing a language (#742) 2025-07-02 05:33:00 +00:00
Brewfile all: do not commit generated JS/CSS to source control (#148) 2025-03-28 14:55:25 -04:00
go.mod Revert "build(deps): bump the gomod group with 6 updates (#873)" (#874) 2025-07-21 01:22:40 +00:00
go.sum Revert "build(deps): bump the gomod group with 6 updates (#873)" (#874) 2025-07-21 01:22:40 +00:00
LICENSE initial import from /x/ monorepo 2025-03-17 19:33:07 -04:00
Makefile Makefile: Build robots2policy (#699) 2025-06-20 11:08:56 -04:00
package-lock.json build(deps-dev): bump the npm group with 3 updates (#872) 2025-07-20 20:56:02 -04:00
package.json build(deps-dev): bump the npm group with 3 updates (#872) 2025-07-20 20:56:02 -04:00
README.md chore(sponsors): add fabulous systems 2025-07-12 23:08:30 +00:00
VERSION chore: release v1.21.0 (#844) 2025-07-16 21:21:20 -04:00
yeetfile.js feat: add robots2policy CLI to convert robots.txt to Anubis CEL (#657) 2025-06-14 23:41:00 -04:00

Anubis

A smiling chibi dark-skinned anthro jackal with brown hair and tall ears looking victorious with a thumbs-up

enbyware GitHub Issues or Pull Requests by label GitHub go.mod Go version language count repo size GitHub Sponsors

Sponsors

Anubis is brought to you by sponsors and donors like:

Diamond Tier

Raptor Computing Systems

Gold Tier

Distrust Terminal Trove canine.tools Weblate Uberspace Wildbase Cat eyes over the word Emma in a serif font Cat eyes over the word Emma in a serif font

Overview

Anubis is a Web AI Firewall Utility that weighs the soul of your connection using one or more challenges in order to protect upstream resources from scraper bots.

This program is designed to help protect the small internet from the endless storm of requests that flood in from AI companies. Anubis is as lightweight as possible to ensure that everyone can afford to protect the communities closest to them.

Anubis is a bit of a nuclear response. This will result in your website being blocked from smaller scrapers and may inhibit "good bots" like the Internet Archive. You can configure bot policy definitions to explicitly allowlist them and we are working on a curated set of "known good" bots to allow for a compromise between discoverability and uptime.

In most cases, you should not need this and can probably get by using Cloudflare to protect a given origin. However, for circumstances where you can't or won't use Cloudflare, Anubis is there for you.

If you want to try this out, connect to anubis.techaro.lol.

Support

If you run into any issues running Anubis, please open an issue. Please include all the information I would need to diagnose your issue.

For live chat, please join the Patreon and ask in the Patron discord in the channel #anubis.

Star History

Star History Chart

Packaging Status

Packaging status

Contributors

Made with contrib.rocks.