Skip to content
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

Unix.select with a mix of sockets and non-sockets is not level triggered on Windows #7665

Open
vicuna opened this issue Nov 2, 2017 · 6 comments

Comments

@vicuna
Copy link

vicuna commented Nov 2, 2017

Original bug ID: 7665
Reporter: gabelevi
Status: new
Resolution: open
Priority: normal
Severity: minor
Platform: win32
OS: Windows 10 Enterprise
OS Version: 1511
Version: 4.03.0
Category: platform support (windows, cross-compilation, etc)
Monitored by: @ygrek @dbuenzli

Bug description

I'm using 4.03.0+mingw64 https://fdopen.github.io/opam-repository-mingw/2016/05/03/ocaml_4_03/

Unix.select should be "level triggered". That is, as long as a fd is ready, it should be returned. This is opposed to being "edge triggered", where the fd would only be returned when it first becomes ready.

On Windows, Unix.select with a mixture of sockets and non-sockets does not return all of the ready fds consistently. The first call behaves correctly, but subsequent calls don't.

Steps to reproduce

I uploaded a script which demonstrates the problem, by selecting both a socket and stdin. For some reason, Unix.select stops reporting the socket as being ready. I ran it on cygwin

$ echo "hello" | ocaml C:/cygwin64/home/glevi/.opam/4.03.0+mingw64c/lib/ocaml/unix.cma testA.ml
Set up socket

Socket is not yet connected, so only stdin should be ready
stdin is ready
sock is not ready

Connected to socket

Now they both should be ready
stdin is ready
sock is ready

But if we call select again we hit the bug
stdin is ready
sock is not ready

And it repros if we call again
stdin is ready
sock is not ready

Individually stdin is readable: true

Individually sock is readable: true

But together it is still buggy
stdin is ready
sock is not ready

File attachments

@vicuna
Copy link
Author

vicuna commented Sep 1, 2018

Comment author: toots

I can confirm that, too. Seen here with a mixture of pipe and network socket. Attached is a minimal script reproducing my case. It happens in a complex scheduling context (liquidsoap) and would be great to see fixed..

Tested with versions: 4.01 & 4.07 so it's been around for a while.

@vicuna
Copy link
Author

vicuna commented Sep 2, 2018

Comment author: toots

I believe this is the relevant documentation about the underlying call:

"The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with a call to the connect, ConnectEx, WSAConnect, WSAConnectByList, or WSAConnectByName function or when a socket is accepted with accept, AcceptEx, or WSAAccept function and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set."

@github-actions
Copy link

github-actions bot commented May 7, 2020

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

@github-actions github-actions bot added the Stale label May 7, 2020
@github-actions github-actions bot closed this as completed Jun 8, 2020
@mroch
Copy link

mroch commented Oct 20, 2021

could this be reopened please?

@gasche gasche removed the Stale label Oct 20, 2021
@gasche gasche reopened this Oct 20, 2021
@gasche
Copy link
Member

gasche commented Oct 20, 2021

This looks like something that needs Windows expertise. (cc @nojb, @dra27, @MisterDA). From the outside it's not clear how to provide the expected behavior on top of a function behaving as described. It looks like Python restricts its own select binding to sockets on Windows.

@github-actions github-actions bot added the Stale label Oct 26, 2022
@dra27
Copy link
Member

dra27 commented Oct 26, 2022

Just to nudge this a tiny bit further: @gasche, I expect that Python does what we used to prior to OCaml 3.11 which is that select is a thin wrapper around the underlying select call which in Winsock only supports socket handles. When Unix.select is passed a mixture of handles, we use a (necessarily) complicated system to wait on all the different classes of handle separately and then emulate the result - either something is wrong in there or, more likely, some extra work is needed to emulate level triggering over edge triggering. However, there's a fast path if all the handles are sockets, when we just use the underlying Winsock select call. This fast path is what is making this bug report quite so subtle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants