* fhandler.h (class fhandler_socket): Remove has_been_closed member.
* fhandler_socket.cc (fhandler_socket::recvfrom): Revert to overlapped I/O. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. * net.cc (wsock_event::prepare): Ditto. (wsock_event::wait): Ditto. Evaluate overlapped result also after calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>). (wsock_event::release): Remove. * wsock_event.h: Revert to overlapped I/O.
This commit is contained in:
		| @@ -1,3 +1,17 @@ | |||||||
|  | 2004-04-03  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* fhandler.h (class fhandler_socket): Remove has_been_closed member. | ||||||
|  | 	* fhandler_socket.cc (fhandler_socket::recvfrom): Revert to | ||||||
|  | 	overlapped I/O. | ||||||
|  | 	(fhandler_socket::recvmsg): Ditto. | ||||||
|  | 	(fhandler_socket::sendto): Ditto. | ||||||
|  | 	(fhandler_socket::sendmsg): Ditto. | ||||||
|  | 	* net.cc (wsock_event::prepare): Ditto. | ||||||
|  | 	(wsock_event::wait): Ditto.  Evaluate overlapped result also after | ||||||
|  | 	calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>). | ||||||
|  | 	(wsock_event::release): Remove. | ||||||
|  | 	* wsock_event.h: Revert to overlapped I/O. | ||||||
|  |  | ||||||
| 2004-04-02  Corinna Vinschen  <corinna@vinschen.de> | 2004-04-02  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* net.cc (wsock_event::release): Use NULL handle in call to | 	* net.cc (wsock_event::release): Use NULL handle in call to | ||||||
|   | |||||||
| @@ -377,7 +377,6 @@ class fhandler_socket: public fhandler_base | |||||||
|   struct _WSAPROTOCOL_INFOA *prot_info_ptr; |   struct _WSAPROTOCOL_INFOA *prot_info_ptr; | ||||||
|   char *sun_path; |   char *sun_path; | ||||||
|   int had_connect_or_listen; |   int had_connect_or_listen; | ||||||
|   int has_been_closed; |  | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   fhandler_socket (); |   fhandler_socket (); | ||||||
|   | |||||||
| @@ -122,7 +122,7 @@ get_inet_addr (const struct sockaddr *in, int inlen, | |||||||
| /* fhandler_socket */ | /* fhandler_socket */ | ||||||
|  |  | ||||||
| fhandler_socket::fhandler_socket () | fhandler_socket::fhandler_socket () | ||||||
|   : fhandler_base (), sun_path (NULL), has_been_closed (0) |   : fhandler_base (), sun_path (NULL) | ||||||
| { | { | ||||||
|   set_need_fork_fixup (); |   set_need_fork_fixup (); | ||||||
|   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, |   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, | ||||||
| @@ -714,7 +714,7 @@ int | |||||||
| fhandler_socket::recvfrom (void *ptr, size_t len, int flags, | fhandler_socket::recvfrom (void *ptr, size_t len, int flags, | ||||||
| 			   struct sockaddr *from, int *fromlen) | 			   struct sockaddr *from, int *fromlen) | ||||||
| { | { | ||||||
|   int res = SOCKET_ERROR; |   int res; | ||||||
|   DWORD ret; |   DWORD ret; | ||||||
|  |  | ||||||
|   flags &= MSG_WINMASK; |   flags &= MSG_WINMASK; | ||||||
| @@ -726,28 +726,19 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags, | |||||||
|     { |     { | ||||||
|       WSABUF wsabuf = { len, (char *) ptr }; |       WSABUF wsabuf = { len, (char *) ptr }; | ||||||
|  |  | ||||||
|       if (is_nonblocking () || has_been_closed) |       if (is_nonblocking ()) | ||||||
| 	res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &ret), | 	res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags, | ||||||
| 			   (DWORD *) &flags, from, fromlen, NULL, NULL); | 			   from, fromlen, | ||||||
|  | 			   NULL, NULL); | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
| 	  wsock_event wsock_evt; | 	  wsock_event wsock_evt; | ||||||
| 	  long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ)); | 	  res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags, | ||||||
| 	  if (wsock_evt.prepare (get_socket (), evt)) | 			     from, fromlen, | ||||||
| 	    { | 			     wsock_evt.prepare (), NULL); | ||||||
|               do |  | ||||||
|                 { | 	  if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) | ||||||
| 		  res = WSARecvFrom (get_socket (), &wsabuf, 1, | 	    ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); | ||||||
| 				     (ret = 0, &ret), (DWORD *) &flags, |  | ||||||
| 				     from, fromlen, NULL, NULL); |  | ||||||
|                 } |  | ||||||
|               while (res == SOCKET_ERROR |  | ||||||
|                      && WSAGetLastError () == WSAEWOULDBLOCK |  | ||||||
| 		     && !has_been_closed |  | ||||||
| 		     && !(res = wsock_evt.wait (get_socket (), |  | ||||||
| 		     				has_been_closed))); |  | ||||||
| 	      wsock_evt.release (get_socket ()); |  | ||||||
| 	    } |  | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -785,7 +776,7 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot) | |||||||
|   struct sockaddr *from = (struct sockaddr *) msg->msg_name; |   struct sockaddr *from = (struct sockaddr *) msg->msg_name; | ||||||
|   int *fromlen = from ? &msg->msg_namelen : NULL; |   int *fromlen = from ? &msg->msg_namelen : NULL; | ||||||
|  |  | ||||||
|   int res = SOCKET_ERROR; |   int res; | ||||||
|  |  | ||||||
|   if (!winsock2_active) |   if (!winsock2_active) | ||||||
|     { |     { | ||||||
| @@ -852,29 +843,21 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot) | |||||||
|  |  | ||||||
|       DWORD ret; |       DWORD ret; | ||||||
|  |  | ||||||
|       if (is_nonblocking () || has_been_closed) |       if (is_nonblocking ()) | ||||||
| 	res = WSARecvFrom (get_socket (), | 	res = WSARecvFrom (get_socket (), | ||||||
| 			   wsabuf, iovcnt, (ret = 0, &ret), (DWORD *) &flags, | 			   wsabuf, iovcnt, &ret, (DWORD *) &flags, | ||||||
| 			   from, fromlen, NULL, NULL); | 			   from, fromlen, | ||||||
|  | 			   NULL, NULL); | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
| 	  wsock_event wsock_evt; | 	  wsock_event wsock_evt; | ||||||
| 	  long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ)); | 	  res = WSARecvFrom (get_socket (), | ||||||
| 	  if (wsock_evt.prepare (get_socket (), evt)) | 			     wsabuf, iovcnt, &ret, (DWORD *) &flags, | ||||||
| 	    { | 			     from, fromlen, | ||||||
|               do | 			     wsock_evt.prepare (), NULL); | ||||||
|                 { |  | ||||||
| 		  res = WSARecvFrom (get_socket (), wsabuf, iovcnt, | 	  if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) | ||||||
| 				     (ret = 0, &ret), (DWORD *) &flags, | 	    ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); | ||||||
| 				     from, fromlen, NULL, NULL); |  | ||||||
|                 } |  | ||||||
|               while (res == SOCKET_ERROR |  | ||||||
| 		     && WSAGetLastError () == WSAEWOULDBLOCK |  | ||||||
| 		     && !has_been_closed |  | ||||||
| 		     && !(res = wsock_evt.wait (get_socket (), |  | ||||||
| 		     				has_been_closed))); |  | ||||||
| 	      wsock_evt.release (get_socket ()); |  | ||||||
| 	    } |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|       if (res == SOCKET_ERROR) |       if (res == SOCKET_ERROR) | ||||||
| @@ -917,9 +900,9 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags, | |||||||
|   sockaddr_in sin; |   sockaddr_in sin; | ||||||
|  |  | ||||||
|   if (to && !get_inet_addr (to, tolen, &sin, &tolen)) |   if (to && !get_inet_addr (to, tolen, &sin, &tolen)) | ||||||
|     return -1; |     return SOCKET_ERROR; | ||||||
|  |  | ||||||
|   int res = SOCKET_ERROR; |   int res; | ||||||
|   DWORD ret; |   DWORD ret; | ||||||
|  |  | ||||||
|   if (!winsock2_active) |   if (!winsock2_active) | ||||||
| @@ -930,35 +913,21 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags, | |||||||
|     { |     { | ||||||
|       WSABUF wsabuf = { len, (char *) ptr }; |       WSABUF wsabuf = { len, (char *) ptr }; | ||||||
|  |  | ||||||
|       if (is_nonblocking () || has_been_closed) |       if (is_nonblocking ()) | ||||||
| 	res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret), | 	res = WSASendTo (get_socket (), &wsabuf, 1, &ret, | ||||||
| 			 flags & MSG_WINMASK, | 			 flags & MSG_WINMASK, | ||||||
| 			 (to ? (const struct sockaddr *) &sin : NULL), tolen, | 			 (to ? (const struct sockaddr *) &sin : NULL), tolen, | ||||||
| 			 NULL, NULL); | 			 NULL, NULL); | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
| 	  wsock_event wsock_evt; | 	  wsock_event wsock_evt; | ||||||
| 	  if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE)) | 	  res = WSASendTo (get_socket (), &wsabuf, 1, &ret, | ||||||
| 	    { |  | ||||||
| 	      do  |  | ||||||
| 		{ |  | ||||||
| 		  res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret), |  | ||||||
| 			   flags & MSG_WINMASK, | 			   flags & MSG_WINMASK, | ||||||
| 				   (to ? (const struct sockaddr *) &sin : NULL), | 			   (to ? (const struct sockaddr *) &sin : NULL), tolen, | ||||||
| 				   tolen, NULL, NULL); | 			   wsock_evt.prepare (), NULL); | ||||||
| 		  if (res != SOCKET_ERROR |  | ||||||
| 		      || WSAGetLastError () != WSAEWOULDBLOCK) | 	  if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) | ||||||
| 		    break; | 	    ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); | ||||||
| 		  if (ret > 0) |  | ||||||
| 		    { |  | ||||||
| 		      res = 0; |  | ||||||
| 		      break; |  | ||||||
| 		    } |  | ||||||
| 		} |  | ||||||
| 	      while (!(res = wsock_evt.wait (get_socket (), has_been_closed)) |  | ||||||
| 		     && !has_been_closed); |  | ||||||
| 	      wsock_evt.release (get_socket ()); |  | ||||||
| 	    } |  | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -998,7 +967,7 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot) | |||||||
|   struct iovec *const iov = msg->msg_iov; |   struct iovec *const iov = msg->msg_iov; | ||||||
|   const int iovcnt = msg->msg_iovlen; |   const int iovcnt = msg->msg_iovlen; | ||||||
|  |  | ||||||
|   int res = SOCKET_ERROR; |   int res; | ||||||
|  |  | ||||||
|   if (!winsock2_active) |   if (!winsock2_active) | ||||||
|     { |     { | ||||||
| @@ -1067,34 +1036,21 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot) | |||||||
|  |  | ||||||
|       DWORD ret; |       DWORD ret; | ||||||
|  |  | ||||||
|       if (is_nonblocking () || has_been_closed) |       if (is_nonblocking ()) | ||||||
| 	res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret), | 	res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags, | ||||||
| 			 flags, (struct sockaddr *) msg->msg_name, | 			 (struct sockaddr *) msg->msg_name, | ||||||
| 			 msg->msg_namelen, NULL, NULL); | 			 msg->msg_namelen, | ||||||
|  | 			 NULL, NULL); | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
| 	  wsock_event wsock_evt; | 	  wsock_event wsock_evt; | ||||||
| 	  if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE)) | 	  res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags, | ||||||
| 	    { |  | ||||||
|               do |  | ||||||
|                 { |  | ||||||
| 		  res = WSASendTo (get_socket (), wsabuf, iovcnt, |  | ||||||
| 		  		   (ret = 0, &ret), flags, |  | ||||||
| 			   (struct sockaddr *) msg->msg_name, | 			   (struct sockaddr *) msg->msg_name, | ||||||
| 				   msg->msg_namelen, NULL, NULL); | 			   msg->msg_namelen, | ||||||
|                   if (res != SOCKET_ERROR | 			   wsock_evt.prepare (), NULL); | ||||||
|                       || WSAGetLastError () != WSAEWOULDBLOCK) |  | ||||||
|                     break; | 	  if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING) | ||||||
|                   if (ret > 0) | 	    ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags); | ||||||
|                     { |  | ||||||
|                       res = 0; |  | ||||||
|                       break; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|               while (!(res = wsock_evt.wait (get_socket (), has_been_closed)) |  | ||||||
| 	             && !has_been_closed); |  | ||||||
| 	      wsock_evt.release (get_socket ()); |  | ||||||
| 	    } |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|       if (res == SOCKET_ERROR) |       if (res == SOCKET_ERROR) | ||||||
|   | |||||||
| @@ -50,83 +50,59 @@ extern "C" | |||||||
|   int sscanf (const char *, const char *, ...); |   int sscanf (const char *, const char *, ...); | ||||||
| }				/* End of "C" section */ | }				/* End of "C" section */ | ||||||
|  |  | ||||||
| bool | LPWSAOVERLAPPED | ||||||
| wsock_event::prepare (int sock, long event_mask) | wsock_event::prepare () | ||||||
| { | { | ||||||
|   WSASetLastError (0); |   LPWSAOVERLAPPED ret = NULL; | ||||||
|   if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT) |  | ||||||
|     debug_printf ("WSACreateEvent: %E"); |  | ||||||
|   else if (WSAEventSelect (sock, event, event_mask) == SOCKET_ERROR) |  | ||||||
|     { |  | ||||||
|       debug_printf ("WSAEventSelect: %E"); |  | ||||||
|       WSACloseEvent (event); |  | ||||||
|       event = WSA_INVALID_EVENT; |  | ||||||
|     } |  | ||||||
|   return event != WSA_INVALID_EVENT; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |   SetLastError (0); | ||||||
| wsock_event::wait (int sock, int &closed) |   if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT) | ||||||
|     { |     { | ||||||
|   int ret = SOCKET_ERROR; |       memset (&ovr, 0, sizeof ovr); | ||||||
|   int wsa_err = 0; |       ovr.hEvent = event; | ||||||
|   WSAEVENT ev[2] = { event, signal_arrived }; |       ret = &ovr; | ||||||
|   switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE)) |  | ||||||
|     { |  | ||||||
|       case WSA_WAIT_EVENT_0: |  | ||||||
|         WSANETWORKEVENTS evts; |  | ||||||
| 	if (!WSAEnumNetworkEvents (sock, event, &evts)) |  | ||||||
| 	  { |  | ||||||
| 	    if (evts.lNetworkEvents & FD_READ) |  | ||||||
| 	      { |  | ||||||
| 		if (evts.iErrorCode[FD_READ_BIT]) |  | ||||||
| 		  wsa_err = evts.iErrorCode[FD_READ_BIT]; |  | ||||||
| 		else |  | ||||||
| 		  ret = 0; |  | ||||||
| 	      } |  | ||||||
| 	    else if (evts.lNetworkEvents & FD_WRITE) |  | ||||||
| 	      { |  | ||||||
| 		if (evts.iErrorCode[FD_WRITE_BIT]) |  | ||||||
| 		  wsa_err = evts.iErrorCode[FD_WRITE_BIT]; |  | ||||||
| 		else |  | ||||||
| 		  ret = 0; |  | ||||||
| 	      } |  | ||||||
| 	    if (evts.lNetworkEvents & FD_CLOSE) |  | ||||||
| 	      { |  | ||||||
| 		closed = 1; |  | ||||||
| 		if (!wsa_err) |  | ||||||
| 		  { |  | ||||||
| 		    if (evts.iErrorCode[FD_CLOSE_BIT]) |  | ||||||
| 		      wsa_err = evts.iErrorCode[FD_CLOSE_BIT]; |  | ||||||
| 		    else |  | ||||||
| 		      ret = 0; |  | ||||||
| 		  } |  | ||||||
| 	      } |  | ||||||
| 	    if (wsa_err) |  | ||||||
| 	      WSASetLastError (wsa_err); |  | ||||||
| 	  } |  | ||||||
| 	break; |  | ||||||
|       case WSA_WAIT_EVENT_0 + 1: |  | ||||||
|         WSASetLastError (WSAEINTR); |  | ||||||
| 	break; |  | ||||||
|       default: |  | ||||||
| 	WSASetLastError (WSAEFAULT); |  | ||||||
|     } |     } | ||||||
|  |   else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */ | ||||||
|  |     WSASetLastError (0); | ||||||
|  |  | ||||||
|  |   debug_printf ("%d = wsock_event::prepare ()", ret); | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| void | int | ||||||
| wsock_event::release (int sock) | wsock_event::wait (int socket, LPDWORD flags) | ||||||
| { | { | ||||||
|   int last_err = WSAGetLastError (); |   int ret = SOCKET_ERROR; | ||||||
|   /* KB 168349: NT4 fails if the event parameter is not NULL. */ |   WSAEVENT ev[2] = { event, signal_arrived }; | ||||||
|   WSAEventSelect (sock, NULL, 0); |   DWORD len; | ||||||
|   WSACloseEvent (event); |  | ||||||
|   unsigned long non_block = 0; |   switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE)) | ||||||
|   if (ioctlsocket (sock, FIONBIO, &non_block)) |     { | ||||||
|     debug_printf ("return to blocking failed: %d", WSAGetLastError ()); |       case WSA_WAIT_EVENT_0: | ||||||
|  | 	if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags)) | ||||||
|  | 	  ret = (int) len; | ||||||
|  | 	break; | ||||||
|  |       case WSA_WAIT_EVENT_0 + 1: | ||||||
|  | 	if (!CancelIo ((HANDLE) socket)) | ||||||
|  | 	  { | ||||||
|  | 	    debug_printf ("CancelIo() %E, fallback to blocking io"); | ||||||
|  | 	    WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags); | ||||||
|  | 	  } | ||||||
|  | 	else if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags) | ||||||
|  | 	         && len > 0) | ||||||
|  | 	  ret = (int) len; | ||||||
| 	else | 	else | ||||||
|     WSASetLastError (last_err); | 	  WSASetLastError (WSAEINTR); | ||||||
|  | 	break; | ||||||
|  |       case WSA_WAIT_FAILED: | ||||||
|  | 	break; | ||||||
|  |       default:			/* Should be impossible. *LOL* */ | ||||||
|  | 	WSASetLastError (WSAEFAULT); | ||||||
|  | 	break; | ||||||
|  |     } | ||||||
|  |   WSACloseEvent (event); | ||||||
|  |   event = NULL; | ||||||
|  |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| WSADATA wsadata; | WSADATA wsadata; | ||||||
|   | |||||||
| @@ -14,13 +14,19 @@ details. */ | |||||||
| class wsock_event | class wsock_event | ||||||
| { | { | ||||||
|   WSAEVENT		event; |   WSAEVENT		event; | ||||||
|  |   WSAOVERLAPPED		ovr; | ||||||
| public: | public: | ||||||
|   wsock_event () : event (NULL) {}; |   wsock_event () : event (NULL) {}; | ||||||
|  |   ~wsock_event () | ||||||
|  |     { | ||||||
|  |       if (event) | ||||||
|  | 	WSACloseEvent (event); | ||||||
|  |       event = NULL; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|   /* The methods are implemented in net.cc */ |   /* The methods are implemented in net.cc */ | ||||||
|   bool prepare (int sock, long event_mask); |   LPWSAOVERLAPPED prepare (); | ||||||
|   int wait (int sock, int &closed); |   int wait (int socket, LPDWORD flags); | ||||||
|   void release (int sock); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif /* __WSOCK_EVENT_H__ */ | #endif /* __WSOCK_EVENT_H__ */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user