* 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:
Corinna Vinschen
2011-04-30 16:34:48 +00:00
parent cbec4110a2
commit 1804be048a
10 changed files with 197 additions and 99 deletions

View File

@ -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;