diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2011-04-30 20:34:48 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2011-04-30 20:34:48 +0400 |
commit | 1804be048ac341df4162dc954e7319adb4ce915c (patch) | |
tree | db6bff3c9af11a7371b343064e6d3f9a03b5acb1 /winsup/cygwin/flock.cc | |
parent | cbec4110a232424225633a593512969aa8e10ac8 (diff) |
* 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.
Diffstat (limited to 'winsup/cygwin/flock.cc')
-rw-r--r-- | winsup/cygwin/flock.cc | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc index 970bde6c1..b4ef9e6a9 100644 --- a/winsup/cygwin/flock.cc +++ b/winsup/cygwin/flock.cc @@ -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; |