Unexpected EINVAL from pthread_join

Corinna Vinschen corinna-cygwin@cygwin.com
Mon Feb 23 15:05:00 GMT 2015


On Feb 23 13:14, Corinna Vinschen wrote:
> On Feb 22 22:54, Lasse Collin wrote:
> > It seems that a signal can cause pthread_join to incorrectly return
> > EINVAL. I debugged it only a little but hopefully someone finds this
> > useful:
> > 
> > In the file thread.cc, function pthread::join, the call to cygwait may
> > return WAIT_SIGNALED if a signal is sent to the process. The switch
> > statement handling the return value assumes that only WAIT_OBJECT_0 and
> > WAIT_CANCELED are possible. The default section of the switch statement
> > has a comment "should never happen" and it returns EINVAL. It might be
> > that the problem occurs only when SA_RESTART isn't used.
> 
> Lasse, I'm sorry, but I can't handle that quickly.  Since you're
> looking into the code and apparently understanding it, maybe you'd
> like to provide patches, too?  Please have a look at
> https://cygwin.com/contrib.html.  Patches <= 10 lines don't even
> need a copyright assignment.

Having said that...

I looked into the Linux man page for pthread_join(1).  It doesn't mention
signals and EINTR at all.  Then I looked into the SUSv4 pages(2) and it
only has this to say:

  The pthread_join() function shall not return an error code of [EINTR].

Searching further on this I found this(3):

  The wait in pthread_join is not broken by a signal. If a thread
  waiting in pthread_join receives a signal that is not masked, if will
  execute the signal handler, and then return to waiting in
  pthread_join.

Taking that at face value, the following patch should do the right
thing, doesn't it?


Index: thread.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/thread.cc,v
retrieving revision 1.296
diff -u -p -r1.296 thread.cc
--- thread.cc	28 Nov 2014 20:46:13 -0000	1.296
+++ thread.cc	23 Feb 2015 12:58:59 -0000
@@ -2399,6 +2399,7 @@ pthread::join (pthread_t *thread, void *
       (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
       (*thread)->mutex.unlock ();
 
+restart_on_signal:
       switch (cygwait ((*thread)->win32_obj_id, cw_infinite, cw_sig | cw_cancel))
 	{
 	case WAIT_OBJECT_0:
@@ -2413,6 +2414,9 @@ pthread::join (pthread_t *thread, void *
 	  joiner->cancel_self ();
 	  // never reached
 	  break;
+	case WAIT_SIGNALED:
+	  debug_printf ("Signal received, restart");
+	  goto restart_on_signal;
 	default:
 	  // should never happen
 	  return EINVAL;



Corinna


(1) http://linux.die.net/man/3/pthread_join
(2) http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html
(3) http://osr600doc.sco.com/man/html.PTHREAD/pthread_join.PTHREAD.html


-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20150223/50d4c7b7/attachment.sig>


More information about the Cygwin mailing list