* fcntl.cc (fcntl64): Call pthread_testcancel.
* fhandler_socket.cc (fhandler_socket::connect): Ditto. (fhandler_socket::accept4): Ditto. (fhandler_socket::recvfrom): Ditto. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. * flock.cc (lf_setlock): Allow to cancel thread running blocking file lock. Try to make code more readable. (lockf): Call pthread_testcancel. * mmap.cc (msync): Ditto. * posix_ipc.cc (ipc_cond_timedwait): Call pthread::static_cancel_self rather than pthread_testcancel. * select.cc (cygwin_select): Call pthread_testcancel. * syscalls.cc (pread): Ditto. (pwrite): Ditto. (readv): Ditto. (writev): Ditto. (open): Ditto. (close): Ditto. (fsync): Ditto. * termios.cc (tcdrain): Ditto. * thread.cc: Align list of cancellation points with above changes. Mark not-implemented functions, too. (cancelable_wait): Don't set unused object indices to WAIT_FAILED since that could result in wrong behaviour. Set them to the invalid value WAIT_TIMEOUT + 1 instead.
This commit is contained in:
		| @@ -957,6 +957,20 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl) | ||||
| 			 "Win32 pid %lu: %E", block->lf_wid); | ||||
| 	  return EDEADLK; | ||||
| 	} | ||||
|  | ||||
|       pthread_t thread = pthread::self (); | ||||
|       HANDLE cancel_event = (thread && thread->cancel_event | ||||
| 			     && thread->cancelstate != PTHREAD_CANCEL_DISABLE) | ||||
| 			    ? thread->cancel_event : NULL; | ||||
|  | ||||
|       int wait_count = 0; | ||||
|       /* The lock is always the first object. */ | ||||
|       const DWORD WAIT_UNLOCKED = WAIT_OBJECT_0; | ||||
|       /* All other wait objects are variable.  */ | ||||
|       DWORD WAIT_PROC_EXITED = WAIT_TIMEOUT + 1; | ||||
|       DWORD WAIT_SIGNAL_ARRIVED = WAIT_TIMEOUT + 1; | ||||
|       DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1; | ||||
|  | ||||
|       SetThreadPriority (GetCurrentThread (), priority); | ||||
|       if (lock->lf_flags & F_POSIX) | ||||
| 	{ | ||||
| @@ -971,15 +985,32 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl) | ||||
| 	      NtClose (obj); | ||||
| 	      return EDEADLK; | ||||
| 	    } | ||||
| 	  HANDLE w4[3] = { obj, proc, signal_arrived }; | ||||
|  | ||||
| 	  HANDLE w4[4] = { obj, proc, signal_arrived, cancel_event }; | ||||
| 	  wait_count = 3; | ||||
| 	  WAIT_PROC_EXITED = WAIT_OBJECT_0 + 1; | ||||
| 	  WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 2; | ||||
| 	  if (cancel_event) | ||||
| 	    { | ||||
| 	      wait_count = 4; | ||||
| 	      WAIT_THREAD_CANCELED = WAIT_OBJECT_0 + 3; | ||||
| 	    } | ||||
| 	  node->wait (); | ||||
| 	  node->UNLOCK (); | ||||
| 	  ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE); | ||||
| 	  ret = WaitForMultipleObjects (wait_count, w4, FALSE, INFINITE); | ||||
| 	  CloseHandle (proc); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  HANDLE w4[2] = { obj, signal_arrived }; | ||||
| 	  HANDLE w4[3] = { obj, signal_arrived, cancel_event }; | ||||
| 	  wait_count = 2; | ||||
| 	  WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + 1; | ||||
| 	  if (cancel_event) | ||||
| 	    { | ||||
| 	      wait_count = 3; | ||||
| 	      WAIT_THREAD_CANCELED = WAIT_OBJECT_0 + 2; | ||||
| 	    } | ||||
|  | ||||
| 	  node->wait (); | ||||
| 	  node->UNLOCK (); | ||||
| 	  /* Unfortunately, since BSD flock locks are not attached to a | ||||
| @@ -988,7 +1019,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl) | ||||
| 	     process left accessing this event object. */ | ||||
| 	  do | ||||
| 	    { | ||||
| 	      ret = WaitForMultipleObjects (2, w4, FALSE, 100L); | ||||
| 	      ret = WaitForMultipleObjects (wait_count, w4, FALSE, 100L); | ||||
| 	    } | ||||
| 	  while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1); | ||||
| 	  /* There's a good chance that the above loop is left with | ||||
| @@ -1002,21 +1033,23 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl) | ||||
|       node->unwait (); | ||||
|       NtClose (obj); | ||||
|       SetThreadPriority (GetCurrentThread (), old_prio); | ||||
|       switch (ret) | ||||
|       if (ret == WAIT_UNLOCKED) | ||||
| 	; /* The lock object has been set to signalled. */ | ||||
|       else if (ret == WAIT_PROC_EXITED) | ||||
| 	; /* For POSIX locks, the process holding the lock has exited. */ | ||||
|       else if (ret == WAIT_SIGNAL_ARRIVED) | ||||
| 	{ | ||||
| 	case WAIT_OBJECT_0: | ||||
| 	  /* The lock object has been set to signalled. */ | ||||
| 	  break; | ||||
| 	case WAIT_OBJECT_0 + 1: | ||||
| 	  /* For POSIX locks, the process holding the lock has exited. */ | ||||
| 	  if (lock->lf_flags & F_POSIX) | ||||
| 	    break; | ||||
| 	  /*FALLTHRU*/ | ||||
| 	case WAIT_OBJECT_0 + 2: | ||||
| 	  /* A signal came in. */ | ||||
| 	  _my_tls.call_signal_handler (); | ||||
| 	  return EINTR; | ||||
| 	default: | ||||
| 	  if (!_my_tls.call_signal_handler ()) | ||||
| 	    return EINTR; | ||||
| 	} | ||||
|       else if (ret == WAIT_THREAD_CANCELED) | ||||
| 	{ | ||||
| 	  /* The thread has been sent a cancellation request. */ | ||||
| 	  pthread::static_cancel_self (); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  system_printf ("Shouldn't happen! ret = %lu, error: %lu\n", | ||||
| 			 ret, GetLastError ()); | ||||
| 	  return geterrno_from_win_error (); | ||||
| @@ -1490,6 +1523,8 @@ lockf (int filedes, int function, _off64_t size) | ||||
|   int cmd; | ||||
|   struct __flock64 fl; | ||||
|  | ||||
|   pthread_testcancel (); | ||||
|  | ||||
|   myfault efault; | ||||
|   if (efault.faulted (EFAULT)) | ||||
|     return -1; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user