-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disable GC during coroutine execution + test #7725
Conversation
I'll investigate macos tomorrow. |
src/libexpr/tests/coro-gc.cc
Outdated
#include "serialise.hh" | ||
|
||
|
||
#define guard_gc(x) GC_register_finalizer((void*)x, finalizer, x##_collected, nullptr, nullptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also be guarded with #if HAVE_BOEHMGC
?
I think the patch for the darwin c file never worked. Its regular stack code is different, so the linux patch doesn't translate to it, and the alt stack that was patched is quite irrelevant; used very shortly during signal handling only. |
I've resorted to disabling GC before entering a coroutine on mac OS. I hope that's an acceptable workaround for now. |
f32e765
to
e8f5588
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few local suggestions, but looks good overall 👍
Note that this isn't really correct in that you could have interleaved coroutines, in which case the first to finish will restart the GC while the other is still running. But it's good-enough for now (we could certainly do something with a counter or a smart use of a shared_ptr
, but let's not over-think it).
src/libutil/serialise.hh
Outdated
public: | ||
DisableGC() {}; | ||
virtual ~DisableGC() {}; | ||
static std::shared_ptr<DisableGC> (*create)(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static std::shared_ptr<DisableGC> (*create)(); | |
static std::function<std::shared_ptr<DisableGC>()> create; |
Doesn't change too much, but let's make this more idiomatic C++
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually don't want std::function here. It's quite an expensive wrapper and allows more weird stuff (like functors and std::bind and lambda captures), so using an old function pointer is probably more typesafe for now.
src/libutil/serialise.hh
Outdated
/* Disabling GC when entering a coroutine (on macos). | ||
::create is to avoid boehm gc dependency in libutil. | ||
*/ | ||
class DisableGC { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we maybe make this a slightly more generic CoroutineContext
or something like that? Just so that
- this layer doesn't have to bother about the GC
- Rather than having all these
#if __APPLE__
inserialise.cc
we can just unconditionally callCoroutineContext.create()
and put this#if
inside the constructor/destructor of theBoehmDisableGC
class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I do want to keep it obvious what it's doing and why, though. I've added the disablegc call inside the coroutine definition now.
I considered having a generic hook system (with std::list and everything) so anywhere in the code can add arbitrary coroutine context hooks, but this seems overkill, slower and less clear.
GC_enable/disable actually does the counting itself. Boehm only enables GC when the amount of calls to enable and disable are equal. |
Before overengineering this workaround, we might consider fixing the problem, which is detecting whether the stack pointer is in the given stack and marking the all the stack sections of the segmented darwin stack if it is not. That'd be the equivalent of the linux solution which works quite well. That's not to mention that the linux solution isn't the final solution either, but we Nix maintainers don't have the bandwidth to make architectural changes to bdwgc. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/tweag-nix-dev-update-44/25546/1 |
Regression test for NixOS#7679
I've added a #define to the patch and disable GC in a coroutine when this is not active. However, the tests now succeed when the patch is not applied, which was the entire point of this PR. |
I would suggest a ./configure warning if gc.h is missing this define, but also, I don't want to touch autoconf today. Maybe tomorrow. |
That's fine, the main requirement is that it doesn't crash. I don't think we have very long running coroutines, unless you're filtering a huge source in terms of number of assessed files, so the likelihood seems quite small that we'll request more memory instead of collecting, for more than once or twice in a row. |
... not over-engineer this, because we may be able to implement the coroutine integration properly in the foreseeable future. |
Alright, added this message. |
This is causing some test failures: https://hydra.nixos.org/build/211782650, https://hydra.nixos.org/build/211782591 |
Ah, great, musl and i686. Hmm. Please revert and I'll debug that. |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/tweag-nix-dev-update-45/26397/1 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/nix-team-report-2022-10-2023-03/27486/1 |
Motivation
Regression test for #7679
Context
Without @roberth's boehmgc-coroutine-sp-fallback patch, nix mostly works but sometimes segfaults. This PR provides a test that should catch this bug.
Checklist for maintainers
Maintainers: tick if completed or explain if not relevant
tests/**.sh
src/*/tests
tests/nixos/*