Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005328OCamlOCaml generalpublic2011-08-03 15:232012-09-25 20:07
Reporterdra 
Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version3.12.0 
Target VersionFixed in Version3.12.1+dev 
Summary0005328: Unix.select leaves sockets in non-blocking mode under Windows
DescriptionSockets seem to be set to non-blocking mode when passed to Unix.select in the Windows port.
Additional InformationThe 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", "").
TagsNo tags attached.
Attached Files? file icon nonblock.ml [^] (800 bytes) 2011-08-03 15:23 [Show Content]
? file icon bla.ml [^] (960 bytes) 2011-10-05 15:41 [Show Content]
patch file icon fix-select-nonblocking.patch [^] (2,186 bytes) 2011-10-05 19:14 [Show Content]
? file icon foo.ml [^] (382 bytes) 2011-10-05 19:14 [Show Content]

- Relationships

-  Notes
(0006144)
toots (reporter)
2011-10-05 12:59

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.
(0006145)
toots (reporter)
2011-10-05 15:42

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.
(0006146)
toots (reporter)
2011-10-05 15:46

Please note that, contrary to the previous example, this one is fully deterministic here..
(0006147)
toots (reporter)
2011-10-05 16:10

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.
(0006148)
toots (reporter)
2011-10-05 18:16

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..
(0006151)
toots (reporter)
2011-10-05 19:16

Please find attached a patch that fixes the issue. I have also added another test, foo.ml, which reproduces the original issue (0004894). Patched compiler produces binaries that work correctly in both cases.
(0006165)
xleroy (administrator)
2011-10-15 11:03

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

- Issue History
Date Modified Username Field Change
2011-08-03 15:23 dra New Issue
2011-08-03 15:23 dra File Added: nonblock.ml
2011-10-05 12:59 toots Note Added: 0006144
2011-10-05 15:41 toots File Added: bla.ml
2011-10-05 15:42 toots Note Added: 0006145
2011-10-05 15:46 toots Note Added: 0006146
2011-10-05 16:10 toots Note Added: 0006147
2011-10-05 18:16 toots Note Added: 0006148
2011-10-05 18:34 doligez Status new => acknowledged
2011-10-05 19:14 toots File Added: fix-select-nonblocking.patch
2011-10-05 19:14 toots File Added: foo.ml
2011-10-05 19:16 toots Note Added: 0006151
2011-10-15 11:03 xleroy Note Added: 0006165
2011-10-15 11:03 xleroy Status acknowledged => resolved
2011-10-15 11:03 xleroy Resolution open => fixed
2011-10-15 11:03 xleroy Fixed in Version => 3.12.1+dev
2012-09-25 20:07 xleroy Status resolved => closed


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker