Skip to content

Fix GeventConnection close() race causing EBADF errors#701

Draft
dkropachev wants to merge 1 commit intomasterfrom
fix/gevent-close-race-614
Draft

Fix GeventConnection close() race causing EBADF errors#701
dkropachev wants to merge 1 commit intomasterfrom
fix/gevent-close-race-614

Conversation

@dkropachev
Copy link
Collaborator

Summary

Fixes the close() race condition in GeventConnection that can cause [Errno 9] Bad file descriptor errors.

  • close() uses kill(block=False) which schedules GreenletExit for the next yield point, then closes the socket immediately
  • If close() is called from a non-gevent thread, the greenlet may still be mid-I/O when the socket closes
  • handle_read()/handle_write() don't catch GreenletExit (unlike eventletreactor)

Changes

  • Add is_closed/is_defunct guards in handle_read() and handle_write() error paths
  • Add GreenletExit exception handling in both I/O handlers (matching eventletreactor pattern)
  • Set last_error in close() when connected_event is not yet set
  • Set last_error on server-initiated close (EOF) in handle_read()

Test plan

  • EVENT_LOOP_MANAGER=gevent tests/unit/io/test_geventreactor.py passes

Refs #614

GeventConnection.close() uses kill(block=False) which schedules
GreenletExit for the next yield point, then closes the socket
immediately. If close() is called from a non-gevent thread, the
greenlet may still be mid-I/O when the socket is closed, causing
EBADF.

- Add is_closed/is_defunct guards in handle_read() and handle_write()
  error paths to silently exit during shutdown
- Add GreenletExit exception handling in both I/O handlers for
  graceful greenlet termination (matching eventletreactor pattern)
- Set last_error in close() when connected_event is not yet set to
  prevent factory() from returning a dead connection
- Set last_error on server-initiated close (EOF) in handle_read()
@dkropachev dkropachev marked this pull request as draft February 14, 2026 16:40
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.

1 participant