Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-04-30 20:34:48 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-04-30 20:34:48 +0400
commit1804be048ac341df4162dc954e7319adb4ce915c (patch)
treedb6bff3c9af11a7371b343064e6d3f9a03b5acb1 /winsup/cygwin/flock.cc
parentcbec4110a232424225633a593512969aa8e10ac8 (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.cc69
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;