Skip to content

Conversation

@gasche
Copy link
Contributor

@gasche gasche commented Oct 16, 2025

This is a proposal to fix #1079. I removed the fine-grained typing of the mutable state of a promise, so that the unsafe casts that were previously used are unnecessary. This should remove the crash observed under multicore usage.

This commit guarantees that, even if we later weaken the type
information available on `state`, we keep precise guarantees on
`result` values -- they are not a subset of possible states anymore,
but a separate type.

There may be a performance impact to this change, so running
benchmarks would be useful.
@gasche
Copy link
Contributor Author

gasche commented Oct 16, 2025

Some of the static discipline in the code is moved around instead of removed entirely.

  1. I keep the distinction between promise states that may be proxies and those that may not.
  2. To preserve the distinction between "pending" states and general states, I boxed the pending states into a result type.

Point (2) may have an impact on performance. (I think that it will be neglectible, but I don't understand which parts of the Lwt core are performance-critical so I am not sure.) Do you know how to run benchmarks to measure the performance impact of this PR?

The static discipline on promise states requires an `Obj.magic` in
promise state update. This appears to work correctly under OCaml 4,
but is known to cause segfaults under concurrent usage with OCaml 5.
@raphael-proust
Copy link
Collaborator

thanks for the contribution :)
I'll try to review in depth it soon

re: perf & bench

The part that needs to be real cheap is the non-cooperating binds. That is the binds (and maps and such) where the promise is already resolved and even more so the binds where the promise is already resolved and the function returns an already resolved promise. These correspond to the part of the program where the user code doesn't do any I/O.

| Error _ as p_result ->
let State_may_now_be_pending_proxy p'' = may_now_be_proxy p'' in
let p'' = underlying p'' in
let _state, p'' = underlying p'' in
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Self-review note: this could be let p'' = underlying_promise p'' (same for the other occurrence of let _state, ... = underlying .. below).

@gasche
Copy link
Contributor Author

gasche commented Nov 20, 2025

I understand from #1079 (comment) that this PR proved difficult to review. I wondered if it's worth having if multi-domain gets temporarily removed from Lwt. I have mixed opinions on this:

  • Following the "if it ain't broke, don't fix it" adage, I would support keeping the code as-is instead of making a non-trivial change to the very core of the implementation.
  • On the other hand the change in fact simplifies the code a bit compared to what was there before. It is not just slightly worse in various places due to a loss of static type information (as I initially would have expected); the change in representation avoids any loss in readability. And on the other hand the scary detailed comments about why Obj.magic is acceptable are gone. I think that if I was a maintainer of Lwt, I would first run benchmarks to see if there are performance regressions, and if the performance is preserved (or improved!) consider reviewing and merging just to make the codebase simpler.

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.

6.0.0-beta00: domainworkers fails with Assertion failed or SIGSEGV sometimes

2 participants