OSDN Git Service

* fcntl.cc (fcntl64): Call pthread_testcancel.
authorcorinna <corinna>
Sat, 30 Apr 2011 16:34:43 +0000 (16:34 +0000)
committercorinna <corinna>
Sat, 30 Apr 2011 16:34:43 +0000 (16:34 +0000)
* 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.

winsup/cygwin/ChangeLog
winsup/cygwin/fcntl.cc
winsup/cygwin/fhandler_socket.cc
winsup/cygwin/flock.cc
winsup/cygwin/mmap.cc
winsup/cygwin/posix_ipc.cc
winsup/cygwin/select.cc
winsup/cygwin/syscalls.cc
winsup/cygwin/termios.cc
winsup/cygwin/thread.cc

index 5b0d8ae..a4b1c2b 100644 (file)
@@ -1,5 +1,35 @@
 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.
        * thread.cc (pthread::pthread): Initialize canceled to false.
        (pthread::cancel): Set canceled before setting cancel_event.
index de13f10..84e5e54 100644 (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;
index d0cf205..1151f89 100644 (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];
index 970bde6..b4ef9e6 100644 (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;
index 8522b6d..059daa1 100644 (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 ())
index 88f5a2e..ec6b6c7 100644 (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;
index 9627096..b3d33c6 100644 (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)
index 40b590a..ee57040 100644 (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)
     {
index 608f030..a59bbd2 100644 (file)
@@ -48,6 +48,8 @@ out:
 extern "C" int
 tcdrain (int fd)
 {
+  pthread_testcancel ();
+
   int res = -1;
 
   termios_printf ("tcdrain");
index 10fc2c6..b4a9b29 100644 (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++;