Skip to content

Conversation

DerGuteMoritz
Copy link
Collaborator

Manifold has a debug mechanism which instruments deferreds so that a warning is logged when they are in an error state with no error handler attached at garbage collection time. Such errors are referred to as "dropped errors" and the instrumented deferreds are called "leak-aware".

The dropped error logging feature is enabled by default but for performance reasons, only every 1024th deferred is made leak-aware (see manifold.deferred/deferred). However, deferreds constructed via manifold.deferred/error-deferred are always leak-aware.

This patch introduces a new option manifold.debug/*leak-aware-deferred-rate* which allows changing the rate of leak-aware deferreds being instantiated, with default still being 1024. When this option is set to to 1 (= every deferred will be leak-aware), dropped errors can be detected more reliably e.g. during testing.

To that end, the patch also includes a test util for instrumenting all tests in a namespace so that they fail when a dropped error was detected. All test namespaces are now instrumented like this (except for :benchmark and :stress tests), which already uncovered a few latent dropped errors. These will be fixed in separate patches.

This was prompted by investigating the causes of clj-commons/aleph#766. One of these was found to originate in Manifold itself which will be addressed in a follow-up PR.

Manifold has a debug mechanism which instruments deferreds so that a warning is logged when they are
in an error state with no error handler attached at garbage collection time. Such errors are
referred to as "dropped errors" and the instrumented deferreds are called "leak-aware".

The dropped error logging feature is enabled by default but for performance reasons, only every
1024th deferred is made leak-aware (see `manifold.deferred/deferred`). However, deferreds
constructed via `manifold.deferred/error-deferred` are always leak-aware.

This patch introduces a new option `manifold.debug/*leak-aware-deferred-rate*` which allows changing
the rate of leak-aware deferreds being instantiated, with default still being 1024. When this option
is set to to 1 (= every deferred will be leak-aware), dropped errors can be detected more reliably
e.g. during testing.

To that end, the patch also includes a test util for instrumenting all tests in a namespace so that
they fail when a dropped error was detected. All test namespaces are now instrumented like
this (except for `:benchmark` and `:stress` tests), which already uncovered a few latent dropped
errors. These will be fixed in separate patches.
Copy link
Collaborator

@KingMob KingMob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm rusty, but it looks ok to me.

Why are we using .bindRoot, and not set! or alter-var-root?

@DerGuteMoritz
Copy link
Collaborator Author

Why are we using .bindRoot, and not set! or alter-var-root?

Dunno, I just mimicked the neighboring prior art for *dropped-error-logging-enabled?* 😄 FWIW, set! doesn't work on regular vars (I don't think there's a first-class API for creating settables) and alter-var-root is awkward to use for setting a constant value. I guess that's why Zach ended up using .bindRoot instead 🤷

I suggest I close this PR here and create a fresh one based on the branch that lives in this repo now (GH doesn't allow changing the source branch on an existing PR ...) so that we can review & merge all fixes into that one. Otherwise we'd have to merge the currently failing build which seems undesirable. WDYT?

@DerGuteMoritz
Copy link
Collaborator Author

I suggest I close this PR here and create a fresh one based on the branch that lives in this repo now (GH doesn't allow changing the source branch on an existing PR ...) so that we can review & merge all fixes into that one. Otherwise we'd have to merge the currently failing build which seems undesirable. WDYT?

Just went ahead and did it (see #245) so that I can start opening those follow-up patch PRs. Hope that's OK!

@KingMob
Copy link
Collaborator

KingMob commented Sep 21, 2025

Why are we using .bindRoot, and not set! or alter-var-root?

Dunno, I just mimicked the neighboring prior art for *dropped-error-logging-enabled?* 😄 FWIW, set! doesn't work on regular vars (I don't think there's a first-class API for creating settables) and alter-var-root is awkward to use for setting a constant value. I guess that's why Zach ended up using .bindRoot instead 🤷

I've never understood why so many Clojure examples use alter-var-root for constants...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants