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 leaves sockets in non-blocking mode under Windows #5328

Closed
vicuna opened this Issue Aug 3, 2011 · 7 comments

Comments

Projects
None yet
1 participant
@vicuna
Copy link
Collaborator

vicuna commented Aug 3, 2011

Original bug ID: 5328
Reporter: @dra27
Status: closed (set by @xavierleroy on 2012-09-25T18:07:21Z)
Resolution: fixed
Priority: normal
Severity: major
Version: 3.12.0
Fixed in version: 3.12.1+dev
Category: ~DO NOT USE (was: OCaml general)
Monitored by: toots

Bug description

Sockets seem to be set to non-blocking mode when passed to Unix.select in the Windows port.

Additional information

The attached (compiled with ocamlopt -o nonblock.exe unix.cmxa nonblock.ml) starts a server on localhost:400. Connecting to that and pressing enter a few times results in a Unix.Unix_error(Unix.EWOULDBLOCK, "recv", "").

File attachments

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

I can totally confirm this one too. Unfortunately, we're a little too busy releasing at the moment. I'll see if I can get some time to write a proper test but here's a brief overview of our situation:

Function A : socket1 ->
try
set_nonblock socket;
Unix.connect socket (...);
clear_nonblock socket
with
| WOULDBLOCK ->
let ,w, = Unix.select [] [socket] [] timeout ;
if w = [] then raise Error ;
clear_nonblock socket

Function B : socket ->
let r,, = Unix.select [socket] [] [] timeout in
if r = [] then raise Error

Scenario:
Function A is called and terminates
Function B is called

Result: socket passed to function B is returned in non-blocking mode.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

I have just attached the file bla.ml which reproduces our issue. When run under windows, on get this exception:

Unix error: A non-blocking socket operation could not be completed immediately.

Which is raised on the second socket while this socket has never been put in non-blocking mode.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

Please note that, contrary to the previous example, this one is fully deterministic here..

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

Ahem... I believe the bug is quite trivial...

In ocaml 3.11, in otherlibs/win32unix/select.c, here's the code that set sockets back to blocking:

  /* WSAEventSelect() automatically sets socket to nonblocking mode.
     Restore the blocking one. */
  iMode = 0;
  check_error(lpSelectData,
    WSAEventSelect((SOCKET)(iterQuery->hFileDescr), aEvents[i], 0) != 0 ||
    ioctlsocket((SOCKET)(iterQuery->hFileDescr), FIONBIO, &iMode) != 0);

Same code in 3.12:

  /* WSAEventSelect() automatically sets socket to nonblocking mode.
     Restore the blocking one. */
  if (iterQuery->uFlagsFd & FLAGS_FD_IS_BLOCKING)
  {
    DEBUG_PRINT("Restore a blocking socket");
    iMode = 1;
    check_error(lpSelectData,
      WSAEventSelect((SOCKET)(iterQuery->hFileDescr), aEvents[i], 0) != 0 ||
      ioctlsocket((SOCKET)(iterQuery->hFileDescr), FIONBIO, &iMode) != 0);

Please not the different value for iMode..

MSDN doc says:
FIONBIO
The *argp parameter is a pointer to an unsigned long value. Set *argp to a nonzero value if the nonblocking mode should be enabled, or zero if the nonblocking mode should be disabled.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

Hmmm. It seems that changing iMode to 0 in the above is not sufficient. Nevertheless, I fail to see how this code can restore anything to blocking mode..

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 5, 2011

Comment author: toots

Please find attached a patch that fixes the issue. I have also added another test, foo.ml, which reproduces the original issue (#4894). Patched compiler produces binaries that work correctly in both cases.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 15, 2011

Comment author: @xavierleroy

Thanks a lot for the patch. I applied it in the 3.12 bugfix branch as well as in the trunk.

@vicuna vicuna closed this Sep 25, 2012

@vicuna vicuna added the bug label Mar 20, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.