Skip to content

Fix listen failing with EISCONN on Windows after a Loop with a StatWatcher is freed - #128

Merged
Watson1978 merged 1 commit into
socketry:mainfrom
Watson1978:fix-win32-evpipe-close
Oct 21, 2026
Merged

Watson1978 merged 1 commit into
socketry:mainfrom
Watson1978:fix-win32-evpipe-close

Conversation

@Watson1978

Copy link
Copy Markdown
Collaborator

Since 1.10.0, a Coolio::Loop with a StatWatcher on Windows creates libev's evpipe, a pair of loopback TCP sockets. When the loop is freed, ev_loop_destroy closed them with the CRT close(), which only calls CloseHandle() and leaves Winsock state behind. A socket later imported from a WSAPROTOCOL_INFO with the same handle value inherits that state, and listen() fails with WSAEISCONN. Fluentd hits this through the socket manager of ServerEngine, as in this job.

This registers the evpipe sockets with Ruby through EV_WIN32_HANDLE_TO_FD and closes them with rb_w32_close(), which calls closesocket(). The new native spec frees 20 such loops and then listens on 30 imported sockets. Before this change, 12 to 18 of them failed with WSAEISCONN on a Windows 10 VM.

Types of Changes

  • Bug fix.

Contribution

🤖 Generated with Claude Code

…tcher is freed

Since 1.10.0, a Loop with a StatWatcher on Windows creates libev's
evpipe, a pair of loopback TCP sockets. ev_loop_destroy closed them
with the CRT close(), which only calls CloseHandle() and leaves Winsock
state behind. A socket later imported from a WSAPROTOCOL_INFO with the
same handle value inherits that state, and listen() fails with
WSAEISCONN. Fluentd hits this through the socket manager of
ServerEngine. Register the evpipe sockets with Ruby and close them with
rb_w32_close(), which calls closesocket().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Watson1978
Watson1978 merged commit 350fc80 into socketry:main Oct 21, 2026
15 checks passed
@Watson1978
Watson1978 deleted the fix-win32-evpipe-close branch October 21, 2026 08:07
Watson1978 added a commit that referenced this pull request Oct 22, 2026
The fixture defined its own copy of the libev configuration, so
settings added to ev_wrap.h, such as the evpipe handling from #128,
did not reach the libev that it tests. Include libev.c, which builds
libev for the extension, instead. Drop ext/libev from the include path
as well, so that ev_wrap.h cannot resolve to the generated header of
the same name in ext/libev.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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