Skip to content

event loop: tolerate unexpected exceptions in post() callbacks#260

Open
hulxv wants to merge 1 commit intobitcoin-core:masterfrom
hulxv:fix/deadlock-on-exception
Open

event loop: tolerate unexpected exceptions in post() callbacks#260
hulxv wants to merge 1 commit intobitcoin-core:masterfrom
hulxv:fix/deadlock-on-exception

Conversation

@hulxv
Copy link
Copy Markdown

@hulxv hulxv commented Mar 19, 2026

If a function posted via EventLoop::post() threw an exception, the event loop would exit without resetting m_post_fn or notifying the condition variable, permanently deadlocking the calling thread in post().

This change catches the exception instead, logs it, and keeps the event loop running so the caller is unblocked and other I/O events continue to be processed.

Fix #259

@DrahtBot
Copy link
Copy Markdown

DrahtBot commented Mar 19, 2026

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Reviews

See the guideline for information on the review process.

Type Reviewers
Stale ACK ryanofsky

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

src/mp/proxy.cpp Outdated
int post_fd{m_post_fd};
KJ_DEFER({
Lock lock(m_mutex);
m_cv.wait(lock.m_lock, [this]() MP_REQUIRES(m_mutex) { return m_num_clients == 0; });
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In commit "fix: EventLoop::post() deadlocks when posted function throws" (c6ad605)

It seems like waiting for clients to be released here might just replace one deadlock with another deadlock in the general case m_post_fn throws and there is not just a single client.

I tend to think if m_post_fn is going to throws, reasonable things to do might be:

  • Abort so this is detected as a bug
  • Or keep executing the event loop, but log an error
  • Or let the exception immediately propagate to the caller like happens currently.

Trying to propagate the exception, but waiting for resources to be freed and possibly hanging seems like it adds more complexity without providing a reliable benefit

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

oh ok, I didn't notice that. thanks for catching it.

I tend to think if m_post_fn is going to throws, reasonable things to do might be:

* Abort so this is detected as a bug

* Or keep executing the event loop, but log an error

* Or let the exception immediately propagate to the caller like happens currently.

I think the best and simplest solution here is keeping the executing of the event loop and just log an error. what do you think?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

re: #260 (comment)

I think the best and simplest solution here is keeping the executing of the event loop and just log an error. what do you think?

Yes I think logging the exception here would be a simple improvement that should help debugging. Would recommend kj::runCatchingExceptions for that and kj::str() to turn the exception into a string.

Using catch (...) { eptr = std::current_exception(); } to catch the exception in the event loop thread and std::rethrow_exception(eptr); to rethrow it EventLoop::post() could be a different improvement that would help debugging, but I don't know if it would add too much complexity.

Keeping the event loop running after the exception is thrown should also be an improvement.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Copy link
Copy Markdown
Collaborator

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Code review ACK 5cf3278. Thanks for the logging improvement!

IMO it would be good to update the commit title, pr title, and PR description to clarify what this change does now, but the change itself looks good.

Copy link
Copy Markdown
Collaborator

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

Thanks for the logging improvement!

Forgot when I wrote this that this change isn't only a logging improvement, but it also changes execution because EventLoop::post will now return on failure instead of hanging, and other I/O events will now continue to be processed. Would be good to mention these things in the pr/commit description and maybe change title to something like "event loop: tolerate unexpected exceptions in post() callbacks"

@hulxv hulxv changed the title fix: EventLoop::post() deadlocks when posted function throws event loop: tolerate unexpected exceptions in post() callbacks Mar 31, 2026
@hulxv hulxv force-pushed the fix/deadlock-on-exception branch from 5cf3278 to 7b26641 Compare March 31, 2026 06:43
@hulxv
Copy link
Copy Markdown
Author

hulxv commented Mar 31, 2026

is there anything else that should be added?

@hulxv hulxv requested a review from ryanofsky March 31, 2026 06:45
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.

bug: EventLoop::post() deadlocks when posted function throws

3 participants