* 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>
+
+ * 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.
/* 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.
void *arg = NULL;
va_list args;
+ pthread_testcancel ();
+
myfault efault;
if (efault.faulted (EFAULT))
return -1;
DWORD err;
int type;
+ pthread_testcancel ();
+
if (!get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret))
return -1;
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))
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,
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
{
struct sockaddr_storage sst;
+ pthread_testcancel ();
+
if (to && !get_inet_addr (to, tolen, &sst, &tolen))
return SOCKET_ERROR;
int
fhandler_socket::sendmsg (const struct msghdr *msg, int flags)
{
+ pthread_testcancel ();
+
/* TODO: Descriptor passing on AF_LOCAL sockets. */
WSABUF wsabuf[msg->msg_iovlen];
"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)
{
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
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
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 ();
int cmd;
struct __flock64 fl;
+ pthread_testcancel ();
+
myfault efault;
if (efault.faulted (EFAULT))
return -1;
syscall_printf ("msync (addr: %p, len %u, flags %x)", addr, len, flags);
+ pthread_testcancel ();
+
LIST_LOCK ();
if (((uintptr_t) addr % getpagesize ())
break;
case WAIT_OBJECT_0 + 2:
if (timer_idx != 2)
- pthread_testcancel ();
+ pthread::static_cancel_self ();
/*FALLTHRU*/
case WAIT_OBJECT_0 + 3:
ret = ETIMEDOUT;
select_printf ("%d, %p, %p, %p, %p", maxfds, readfds, writefds, exceptfds, to);
+ pthread_testcancel ();
+
if (!readfds)
readfds = dummy_readfds;
if (!writefds)
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)
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)
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 ();
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);
mode_t mode = 0;
syscall_printf ("open (%s, %p)", unix_path, flags);
+ pthread_testcancel ();
myfault efault;
if (efault.faulted (EFAULT))
/* errno already set */;
syscall_printf ("close (%d)", fd);
+ pthread_testcancel ();
+
MALLOC_CHECK;
cygheap_fdget cfd (fd, true);
if (cfd < 0)
extern "C" int
fsync (int fd)
{
+ pthread_testcancel ();
cygheap_fdget cfd (fd);
if (cfd < 0)
{
extern "C" int
tcdrain (int fd)
{
+ pthread_testcancel ();
+
int res = -1;
termios_printf ("tcdrain");
/* 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 ()
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 ()
fchmodat ()
fchown ()
fchownat ()
- fclose ()
- fcntl () (any value)
+ * fclose ()
+ * fcntl () (any value)
fflush ()
fgetc ()
fgetpos ()
fgets ()
fgetwc ()
fgetws ()
- fmtmsg ()
+ o fmtmsg ()
fopen ()
fpathconf ()
fprintf ()
getchar ()
getchar_unlocked ()
getcwd ()
- getdate ()
+ o getdate ()
getdelim ()
getgrent ()
getgrgid ()
getlogin ()
getlogin_r ()
getnameinfo ()
- getnetbyaddr ()
- getnetbyname ()
- getnetent ()
+ o getnetbyaddr ()
+ o getnetbyname ()
+ o getnetent ()
getopt () (if opterr is nonzero)
getprotobyname ()
getprotobynumber ()
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 ()
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 ()
semop ()
setgrent ()
sethostent ()
- setnetent ()
+ o setnetent ()
setprotoent ()
setpwent ()
setservent ()
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++;
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++;