* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle
overlapped_fallback error condition like other error conditions. Set res carefully and specifically for each condition rather than resorting to a default. (fhandler_base_overlapped::write_overlapped): Preserve errno in overlapped_fallback condition. Correct write_overlapped_fallback to avoid inappropriate looping. (fhandler_base_overlapped::write_overlapped_fallback): Add some more comments.
This commit is contained in:
		| @@ -1,3 +1,15 @@ | |||||||
|  | 2011-03-09  Christopher Faylor  <me.cygwin2011@cgf.cx> | ||||||
|  |  | ||||||
|  | 	* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Handle | ||||||
|  | 	overlapped_fallback error condition like other error conditions.  Set | ||||||
|  | 	res carefully and specifically for each condition rather than resorting | ||||||
|  | 	to a default. | ||||||
|  | 	(fhandler_base_overlapped::write_overlapped): Preserve errno in | ||||||
|  | 	overlapped_fallback condition.  Correct write_overlapped_fallback to | ||||||
|  | 	avoid inappropriate looping. | ||||||
|  | 	(fhandler_base_overlapped::write_overlapped_fallback): Add some more | ||||||
|  | 	comments. | ||||||
|  |  | ||||||
| 2011-03-09  Christopher Faylor  <me.cygwin@cgf.cx> | 2011-03-09  Christopher Faylor  <me.cygwin@cgf.cx> | ||||||
|  |  | ||||||
| 	* fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops! | 	* fhandler.cc (fhandler_base_overlapped::write_overlapp): Oops! | ||||||
|   | |||||||
| @@ -1731,14 +1731,15 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte | |||||||
|   if (!get_overlapped ()) |   if (!get_overlapped ()) | ||||||
|     return inres ? overlapped_success : overlapped_error; |     return inres ? overlapped_success : overlapped_error; | ||||||
|  |  | ||||||
|  |   wait_return res; | ||||||
|   DWORD err = GetLastError (); |   DWORD err = GetLastError (); | ||||||
|   if (err == ERROR_NO_SYSTEM_RESOURCES) |   if (err == ERROR_NO_SYSTEM_RESOURCES) | ||||||
|     return overlapped_fallback; |     res = overlapped_fallback; | ||||||
|  |   else if (nonblocking) | ||||||
|   wait_return res = overlapped_error; |  | ||||||
|   if (nonblocking) |  | ||||||
|     { |     { | ||||||
|       if (inres || err == ERROR_IO_PENDING) |       if (!inres && err != ERROR_IO_PENDING) | ||||||
|  | 	res = overlapped_error; | ||||||
|  |       else | ||||||
| 	{ | 	{ | ||||||
| 	  io_pending = err == ERROR_IO_PENDING; | 	  io_pending = err == ERROR_IO_PENDING; | ||||||
| 	  if (writing && !inres) | 	  if (writing && !inres) | ||||||
| @@ -1747,7 +1748,9 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte | |||||||
| 	  err = 0; | 	  err = 0; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   else if (inres || err == ERROR_IO_PENDING) |   else if (!inres && err != ERROR_IO_PENDING) | ||||||
|  |     res = overlapped_error; | ||||||
|  |   else | ||||||
|     { |     { | ||||||
| #ifdef DEBUGGING | #ifdef DEBUGGING | ||||||
|       if (!get_overlapped ()->hEvent) |       if (!get_overlapped ()->hEvent) | ||||||
| @@ -1768,10 +1771,13 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte | |||||||
|       if (signalled) |       if (signalled) | ||||||
| 	{ | 	{ | ||||||
| 	  debug_printf ("got a signal"); | 	  debug_printf ("got a signal"); | ||||||
| 	  if (!_my_tls.call_signal_handler ()) | 	  if (_my_tls.call_signal_handler ()) | ||||||
| 	    set_errno (EINTR); |  | ||||||
| 	  else |  | ||||||
| 	    res = overlapped_signal; | 	    res = overlapped_signal; | ||||||
|  | 	  else | ||||||
|  | 	    { | ||||||
|  | 	      set_errno (EINTR); | ||||||
|  | 	      res = overlapped_error; | ||||||
|  | 	    } | ||||||
| 	  *bytes = (DWORD) -1; | 	  *bytes = (DWORD) -1; | ||||||
| 	  err = 0; | 	  err = 0; | ||||||
| 	} | 	} | ||||||
| @@ -1779,30 +1785,30 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte | |||||||
| 	{ | 	{ | ||||||
| 	  err = GetLastError (); | 	  err = GetLastError (); | ||||||
| 	  debug_printf ("GetOverLappedResult failed, bytes %u", *bytes); | 	  debug_printf ("GetOverLappedResult failed, bytes %u", *bytes); | ||||||
|  | 	  res = overlapped_error; | ||||||
| 	} | 	} | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
|  | 	  err = 0; | ||||||
| 	  debug_printf ("normal %s, %u bytes", writing ? "write" : "read", *bytes); | 	  debug_printf ("normal %s, %u bytes", writing ? "write" : "read", *bytes); | ||||||
| 	  res = overlapped_success; | 	  res = overlapped_success; | ||||||
| 	  err = 0; |  | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   if (!err) |   if (!err) | ||||||
|     /* nothing to do */; |     /* nothing to do */; | ||||||
|   else if (err != ERROR_HANDLE_EOF && err != ERROR_BROKEN_PIPE) |   else if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE) | ||||||
|     { |  | ||||||
|       debug_printf ("err %u", err); |  | ||||||
|       __seterrno_from_win_error (err); |  | ||||||
|       *bytes = (DWORD) -1; |  | ||||||
|       res = overlapped_error; |  | ||||||
|     } |  | ||||||
|   else |  | ||||||
|     { |     { | ||||||
|       debug_printf ("EOF"); |       debug_printf ("EOF"); | ||||||
|       *bytes = 0; |       *bytes = 0; | ||||||
|       res = overlapped_success; |       res = overlapped_success; | ||||||
|     } |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       debug_printf ("err %u", err); | ||||||
|  |       __seterrno_from_win_error (err); | ||||||
|  |       *bytes = (DWORD) -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   if (writing && (err == ERROR_NO_DATA || err == ERROR_BROKEN_PIPE)) |   if (writing && (err == ERROR_NO_DATA || err == ERROR_BROKEN_PIPE)) | ||||||
|     raise (SIGPIPE); |     raise (SIGPIPE); | ||||||
| @@ -1848,6 +1854,7 @@ fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len) | |||||||
|     nbytes = (DWORD) -1; |     nbytes = (DWORD) -1; | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|  |       int last_errno = get_errno (); | ||||||
|       bool keep_looping; |       bool keep_looping; | ||||||
|       if (is_nonblocking () && max_atomic_write && len > max_atomic_write) |       if (is_nonblocking () && max_atomic_write && len > max_atomic_write) | ||||||
| 	len = max_atomic_write; | 	len = max_atomic_write; | ||||||
| @@ -1857,12 +1864,13 @@ fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len) | |||||||
| 				get_overlapped ()); | 				get_overlapped ()); | ||||||
| 	  switch (wait_overlapped (res, true, &nbytes, is_nonblocking (), (size_t) len)) | 	  switch (wait_overlapped (res, true, &nbytes, is_nonblocking (), (size_t) len)) | ||||||
| 	    { | 	    { | ||||||
| 	    case overlapped_fallback: |  | ||||||
| 	      nbytes = write_overlapped_fallback (ptr, len); |  | ||||||
| 	      /* fall through intentionally */; |  | ||||||
| 	    case overlapped_signal: | 	    case overlapped_signal: | ||||||
| 	      keep_looping = true; | 	      keep_looping = true; | ||||||
| 	      break; | 	      break; | ||||||
|  | 	    case overlapped_fallback: | ||||||
|  | 	      set_errno (last_errno);	/* Avoid setting a random EFBIG errno */ | ||||||
|  | 	      nbytes = write_overlapped_fallback (ptr, len); | ||||||
|  | 	      /* fall through intentionally */; | ||||||
| 	    default:	/* Added to quiet gcc */ | 	    default:	/* Added to quiet gcc */ | ||||||
| 	    case overlapped_success: | 	    case overlapped_success: | ||||||
| 	    case overlapped_error: | 	    case overlapped_error: | ||||||
| @@ -1885,6 +1893,7 @@ ssize_t __stdcall __attribute__ ((regparm (3))) | |||||||
| fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t orig_len) | fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t orig_len) | ||||||
| { | { | ||||||
|   size_t chunk; |   size_t chunk; | ||||||
|  |   /* So far, in testing, only the first if test has been necessary */ | ||||||
|   if (orig_len > MAX_OVERLAPPED_WRITE_LEN) |   if (orig_len > MAX_OVERLAPPED_WRITE_LEN) | ||||||
|     chunk = MAX_OVERLAPPED_WRITE_LEN; |     chunk = MAX_OVERLAPPED_WRITE_LEN; | ||||||
|   else if (orig_len > MIN_OVERLAPPED_WRITE_LEN) |   else if (orig_len > MIN_OVERLAPPED_WRITE_LEN) | ||||||
| @@ -1893,6 +1902,10 @@ fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t ori | |||||||
|     chunk = orig_len / 4; |     chunk = orig_len / 4; | ||||||
|   ssize_t nbytes = 0; |   ssize_t nbytes = 0; | ||||||
|   DWORD nbytes_now = 0; |   DWORD nbytes_now = 0; | ||||||
|  |   /* Write to fd in smaller chunks, accumlating a total. | ||||||
|  |      If there's an error, just return the accumulated total | ||||||
|  |      unless the first write fails, in which case return value | ||||||
|  |      from wait_overlapped(). */ | ||||||
|   while ((size_t) nbytes < orig_len) |   while ((size_t) nbytes < orig_len) | ||||||
|     { |     { | ||||||
|       size_t left = orig_len - nbytes; |       size_t left = orig_len - nbytes; | ||||||
| @@ -1915,7 +1928,7 @@ fhandler_base_overlapped::write_overlapped_fallback (const void *ptr, size_t ori | |||||||
| 	case overlapped_signal: | 	case overlapped_signal: | ||||||
| 	  break;			/* keep looping */ | 	  break;			/* keep looping */ | ||||||
| 	case overlapped_error: | 	case overlapped_error: | ||||||
| 	case overlapped_fallback:	/* Could make this more adaptive | 	case overlapped_fallback:	/* XXX Could make this more adaptive | ||||||
| 					   if needed */ | 					   if needed */ | ||||||
| 	  orig_len = 0;			/* terminate loop */ | 	  orig_len = 0;			/* terminate loop */ | ||||||
| 	  break; | 	  break; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user