* 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

@ -1,3 +1,33 @@
2011-04-30 Corinna Vinschen <corinna@vinschen.de>
* 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.
2011-04-30 Corinna Vinschen <corinna@vinschen.de>
* thread.h (class pthread): Add bool member canceled.

View File

@ -1,7 +1,7 @@
/* fcntl.cc: fcntl syscall
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2008,
2009, 2010 Red Hat, Inc.
2009, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@ -26,6 +26,8 @@ fcntl64 (int fd, int cmd, ...)
void *arg = NULL;
va_list args;
pthread_testcancel ();
myfault efault;
if (efault.faulted (EFAULT))
return -1;

View File

@ -1026,6 +1026,8 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
DWORD err;
int type;
pthread_testcancel ();
if (!get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret))
return -1;
@ -1140,6 +1142,8 @@ fhandler_socket::accept4 (struct sockaddr *peer, int *len, int flags)
struct sockaddr_storage lpeer;
int llen = sizeof (struct sockaddr_storage);
pthread_testcancel ();
int res = 0;
while (!(res = wait_for_events (FD_ACCEPT | FD_CLOSE, 0))
&& (res = ::accept (get_socket (), (struct sockaddr *) &lpeer, &llen))
@ -1473,6 +1477,8 @@ ssize_t
fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen)
{
pthread_testcancel ();
WSABUF wsabuf = { len, (char *) ptr };
WSAMSG wsamsg = { from, from && fromlen ? *fromlen : 0,
&wsabuf, 1,
@ -1487,6 +1493,8 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
ssize_t
fhandler_socket::recvmsg (struct msghdr *msg, int flags)
{
pthread_testcancel ();
/* TODO: Descriptor passing on AF_LOCAL sockets. */
/* Disappointing but true: Even if WSARecvMsg is supported, it's only
@ -1626,6 +1634,8 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
{
struct sockaddr_storage sst;
pthread_testcancel ();
if (to && !get_inet_addr (to, tolen, &sst, &tolen))
return SOCKET_ERROR;
@ -1640,6 +1650,8 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
int
fhandler_socket::sendmsg (const struct msghdr *msg, int flags)
{
pthread_testcancel ();
/* TODO: Descriptor passing on AF_LOCAL sockets. */
WSABUF wsabuf[msg->msg_iovlen];

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;

View File

@ -1169,6 +1169,8 @@ msync (void *addr, size_t len, int flags)
syscall_printf ("msync (addr: %p, len %u, flags %x)", addr, len, flags);
pthread_testcancel ();
LIST_LOCK ();
if (((uintptr_t) addr % getpagesize ())

View File

@ -227,7 +227,7 @@ restart1:
break;
case WAIT_OBJECT_0 + 2:
if (timer_idx != 2)
pthread_testcancel ();
pthread::static_cancel_self ();
/*FALLTHRU*/
case WAIT_OBJECT_0 + 3:
ret = ETIMEDOUT;

View File

@ -96,6 +96,8 @@ cygwin_select (int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
select_printf ("%d, %p, %p, %p, %p", maxfds, readfds, writefds, exceptfds, to);
pthread_testcancel ();
if (!readfds)
readfds = dummy_readfds;
if (!writefds)

View File

@ -912,6 +912,8 @@ EXPORT_ALIAS (read, _read)
extern "C" ssize_t
pread (int fd, void *ptr, size_t len, _off64_t off)
{
pthread_testcancel ();
ssize_t res;
cygheap_fdget cfd (fd);
if (cfd < 0)
@ -927,6 +929,8 @@ pread (int fd, void *ptr, size_t len, _off64_t off)
extern "C" ssize_t
pwrite (int fd, void *ptr, size_t len, _off64_t off)
{
pthread_testcancel ();
ssize_t res;
cygheap_fdget cfd (fd);
if (cfd < 0)
@ -956,6 +960,8 @@ EXPORT_ALIAS (write, _write)
extern "C" ssize_t
readv (int fd, const struct iovec *const iov, const int iovcnt)
{
pthread_testcancel ();
extern int sigcatchers;
const int e = get_errno ();
@ -1039,6 +1045,8 @@ done:
extern "C" ssize_t
writev (const int fd, const struct iovec *const iov, const int iovcnt)
{
pthread_testcancel ();
int res = -1;
const ssize_t tot = check_iovec_for_write (iov, iovcnt);
@ -1096,6 +1104,7 @@ open (const char *unix_path, int flags, ...)
mode_t mode = 0;
syscall_printf ("open (%s, %p)", unix_path, flags);
pthread_testcancel ();
myfault efault;
if (efault.faulted (EFAULT))
/* errno already set */;
@ -1206,6 +1215,8 @@ close (int fd)
syscall_printf ("close (%d)", fd);
pthread_testcancel ();
MALLOC_CHECK;
cygheap_fdget cfd (fd, true);
if (cfd < 0)
@ -1480,6 +1491,7 @@ _fstat_r (struct _reent *ptr, int fd, struct __stat32 *buf)
extern "C" int
fsync (int fd)
{
pthread_testcancel ();
cygheap_fdget cfd (fd);
if (cfd < 0)
{

View File

@ -48,6 +48,8 @@ out:
extern "C" int
tcdrain (int fd)
{
pthread_testcancel ();
int res = -1;
termios_printf ("tcdrain");

View File

@ -568,79 +568,80 @@ pthread::cancel ()
/* TODO: Insert pthread_testcancel into the required functions.
Here are the lists of required and optional functions per POSIX.1-2001
and POSIX.1-2008. A start (*) indicates that the Cygwin function already
is a cancellation point (aka "calls pthread_testcancel").
and POSIX.1-2008. A star (*) indicates that the Cygwin function already
is a cancellation point (aka "calls pthread_testcancel"), an o (o)
indicates that the function is not implemented in Cygwin.
Required cancellation points:
accept ()
aio_suspend ()
clock_nanosleep ()
* accept ()
o aio_suspend ()
o clock_nanosleep ()
* close ()
connect ()
* connect ()
* creat ()
fcntl () F_SETLKW
fdatasync ()
fsync ()
getmsg ()
getpmsg ()
lockf () F_LOCK
* fcntl () F_SETLKW
* fdatasync ()
* fsync ()
o getmsg ()
o getpmsg ()
* lockf () F_LOCK
* mq_receive ()
* mq_send ()
* mq_timedreceive ()
* mq_timedsend ()
msgrcv ()
msgsnd ()
msync ()
nanosleep ()
open ()
openat ()
* msync ()
* nanosleep ()
* open ()
* openat ()
* pause ()
poll ()
pread ()
* pread ()
pselect ()
* pthread_cond_timedwait ()
* pthread_cond_wait ()
* pthread_join ()
* pthread_testcancel ()
putmsg ()
putpmsg ()
pwrite ()
read ()
readv ()
recv ()
recvfrom ()
recvmsg ()
o putmsg ()
o putpmsg ()
* pwrite ()
* read ()
* readv ()
* recv ()
* recvfrom ()
* recvmsg ()
select ()
* sem_timedwait ()
* sem_wait ()
send ()
sendmsg ()
sendto ()
* send ()
* sendmsg ()
* sendto ()
* sigpause ()
* sigsuspend ()
sigtimedwait ()
sigwait ()
sigwaitinfo ()
o sigtimedwait ()
* sigwait ()
* sigwaitinfo ()
* sleep ()
* system ()
tcdrain ()
* tcdrain ()
* usleep ()
* wait ()
* wait3()
waitid ()
o waitid ()
* waitpid ()
write ()
writev ()
* write ()
* writev ()
Optional cancellation points:
access ()
asctime ()
asctime_r ()
catclose ()
catgets ()
catopen ()
catclose () Implemented externally: libcatgets
catgets () Implemented externally: libcatgets
catopen () Implemented externally: libcatgets
chmod ()
chown ()
closedir ()
@ -648,18 +649,18 @@ pthread::cancel ()
ctermid ()
ctime ()
ctime_r ()
dbm_close ()
dbm_delete ()
dbm_fetch ()
dbm_nextkey ()
dbm_open ()
dbm_store ()
dbm_close () Implemented externally: libgdbm
dbm_delete () Implemented externally: libgdbm
dbm_fetch () Implemented externally: libgdbm
dbm_nextkey () Implemented externally: libgdbm
dbm_open () Implemented externally: libgdbm
dbm_store () Implemented externally: libgdbm
dlclose ()
dlopen ()
dprintf ()
endgrent ()
endhostent ()
endnetent ()
o endnetent ()
endprotoent ()
endpwent ()
endservent ()
@ -669,15 +670,15 @@ pthread::cancel ()
fchmodat ()
fchown ()
fchownat ()
fclose ()
fcntl () (any value)
* fclose ()
* fcntl () (any value)
fflush ()
fgetc ()
fgetpos ()
fgets ()
fgetwc ()
fgetws ()
fmtmsg ()
o fmtmsg ()
fopen ()
fpathconf ()
fprintf ()
@ -706,7 +707,7 @@ pthread::cancel ()
getchar ()
getchar_unlocked ()
getcwd ()
getdate ()
o getdate ()
getdelim ()
getgrent ()
getgrgid ()
@ -722,9 +723,9 @@ pthread::cancel ()
getlogin ()
getlogin_r ()
getnameinfo ()
getnetbyaddr ()
getnetbyname ()
getnetent ()
o getnetbyaddr ()
o getnetbyname ()
o getnetent ()
getopt () (if opterr is nonzero)
getprotobyname ()
getprotobynumber ()
@ -745,15 +746,15 @@ pthread::cancel ()
getwchar ()
getwd ()
glob ()
iconv_close ()
iconv_open ()
iconv_close () Implemented externally: libiconv
iconv_open () Implemented externally: libiconv
ioctl ()
link ()
linkat ()
lio_listio ()
o lio_listio ()
localtime ()
localtime_r ()
lockf ()
* lockf ()
lseek ()
lstat ()
mkdir ()
@ -776,28 +777,28 @@ pthread::cancel ()
posix_fallocate ()
posix_madvise ()
posix_openpt ()
posix_spawn ()
posix_spawnp ()
posix_trace_clear ()
posix_trace_close ()
posix_trace_create ()
posix_trace_create_withlog ()
posix_trace_eventtypelist_getnext_id ()
posix_trace_eventtypelist_rewind ()
posix_trace_flush ()
posix_trace_get_attr ()
posix_trace_get_filter ()
posix_trace_get_status ()
posix_trace_getnext_event ()
posix_trace_open ()
posix_trace_rewind ()
posix_trace_set_filter ()
posix_trace_shutdown ()
posix_trace_timedgetnext_event ()
posix_typed_mem_open ()
o posix_spawn ()
o posix_spawnp ()
o posix_trace_clear ()
o posix_trace_close ()
o posix_trace_create ()
o posix_trace_create_withlog ()
o posix_trace_eventtypelist_getnext_id ()
o posix_trace_eventtypelist_rewind ()
o posix_trace_flush ()
o posix_trace_get_attr ()
o posix_trace_get_filter ()
o posix_trace_get_status ()
o posix_trace_getnext_event ()
o posix_trace_open ()
o posix_trace_rewind ()
o posix_trace_set_filter ()
o posix_trace_shutdown ()
o posix_trace_timedgetnext_event ()
o posix_typed_mem_open ()
printf ()
psiginfo ()
psignal ()
o psiginfo ()
o psignal ()
pthread_rwlock_rdlock ()
pthread_rwlock_timedrdlock ()
pthread_rwlock_timedwrlock ()
@ -825,7 +826,7 @@ pthread::cancel ()
semop ()
setgrent ()
sethostent ()
setnetent ()
o setnetent ()
setprotoent ()
setpwent ()
setservent ()
@ -908,7 +909,7 @@ cancelable_wait (HANDLE object, DWORD timeout,
DWORD cancel_n;
if (cancel_action == cw_no_cancel || !pthread::is_good_object (&thread) ||
thread->cancelstate == PTHREAD_CANCEL_DISABLE)
cancel_n = (DWORD) -1;
cancel_n = WAIT_TIMEOUT + 1;
else
{
cancel_n = WAIT_OBJECT_0 + num++;
@ -917,7 +918,7 @@ cancelable_wait (HANDLE object, DWORD timeout,
DWORD sig_n;
if (sig_wait == cw_sig_nosig || &_my_tls != _main_tls)
sig_n = (DWORD) -1;
sig_n = WAIT_TIMEOUT + 1;
else
{
sig_n = WAIT_OBJECT_0 + num++;