public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: Florian Weimer <fweimer@redhat.com>,
	Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org>
Subject: Re: [PATCH v2 2/9] nptl: Deallocate the thread stack on setup failure (BZ #19511)
Date: Tue, 1 Jun 2021 10:55:43 -0300	[thread overview]
Message-ID: <6d2dc011-054b-56be-7ba7-9fdd91003bb6@linaro.org> (raw)
In-Reply-To: <69aac17c-75e1-5b80-7df7-1dc09dea18b4@linaro.org>



On 01/06/2021 10:08, Adhemerval Zanella wrote:
> 
> 
> On 01/06/2021 05:32, Florian Weimer wrote:
>> * Adhemerval Zanella via Libc-alpha:
>>
>>> @@ -424,17 +409,22 @@ start_thread (void *arg)
>>>  	 have ownership (see CONCURRENCY NOTES above).  */
>>>        if (__glibc_unlikely (pd->stopped_start))
>>>  	{
>>>  	  /* Get the lock the parent locked to force synchronization.  */
>>>  	  lll_lock (pd->lock, LLL_PRIVATE);
>>>  
>>>  	  /* We have ownership of PD now.  */
>>> +	  if (pd->setup_failed == 1)
>>> +	    {
>>> +	      /* In the case of a failed setup, the created thread will be
>>> +		 responsible to free up the allocated resources.  The
>>> +		 detached mode ensure it won't be joined and it will trigger
>>> +		 the required cleanup.  */
>>> +	      pd->joinid = pd;
>>> +	      __do_cancel ();
>>> +	    }
>>>  
>>>  	  /* And give it up right away.  */
>>>  	  lll_unlock (pd->lock, LLL_PRIVATE);
>>>  	}
>>
>> I don't think this is quite right.  The failed thread should not linger
>> around after pthread_create has reported failure to the caller.  It's
>> better than what we had before, so maybe we should use this version and
>> clean it up further later.
> 
> Agreed, but I think this is really an improvement over current strategy
> as I commented earlier [1].  I think to proper fix would move the
> lock prior any initialization so we don't need to run any unwinding
> operations, skip directly to INTERNAL_SYSCALL_CALL (exit, 0), and let the
> parent join the thread and do the resource deallocation.
> 
>>
>> At the point of the __do_cancel call, unwinding may not yet initialized,
>> so the implied dlopen happens on a potentially very small stack.  It
>> should be possible to replace it with a goto to the cleanup code.  Or
>> maybe put the cleanup code into a separate function and call it here and
>> on the regular cleanup path.
>>
>> Apart from that, it looks fine to me.
> 
> The __do_cancel is not done really in asynchronous mode, so it will use
> the allocated thread stack for the dlopen.  But I think with a better
> strategy to move the 'struct thread' lock earlier than any initialization
> will avoid such issue.
> 
>>
>> Thanks,
>> Florian
>>
> 
> [1] https://sourceware.org/pipermail/libc-alpha/2021-May/126879.html
> 

The patch below on top of this patch implements the synchronous thread
join in case of setup failure.  It shows no regressions on testcases,
and it is slight better because it avoid calling the __pthread_unwind for
such cases (and issuing the libgcc dlopen)

In fact since there is no registered user case that might required
calling either cancellation cleanup handler or thread destructors,
I think there is no need to actually issue a pthread_exit like
termination.

--

diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 018af30c85..7a4c742416 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -346,6 +346,23 @@ start_thread (void *arg)
 {
   struct pthread *pd = arg;
 
+  /* We are either in (a) or (b), and in either case we either own PD already
+     (2) or are about to own PD (1), and so our only restriction would be that
+     we can't free PD until we know we have ownership (see CONCURRENCY NOTES
+     above).  */
+  if (__glibc_unlikely (pd->stopped_start))
+    {
+      /* Get the lock the parent locked to force synchronization.  */
+      lll_lock (pd->lock, LLL_PRIVATE);
+
+      /* We have ownership of PD now.  */
+      if (pd->setup_failed == 1)
+	goto out;
+
+      /* And give it up right away.  */
+      lll_unlock (pd->lock, LLL_PRIVATE);
+     }
+
   /* Initialize resolver state pointer.  */
   __resp = &pd->res;
 
@@ -403,30 +420,6 @@ start_thread (void *arg)
       /* Store the new cleanup handler info.  */
       THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
 
-      /* We are either in (a) or (b), and in either case we either own
-         PD already (2) or are about to own PD (1), and so our only
-	 restriction would be that we can't free PD until we know we
-	 have ownership (see CONCURRENCY NOTES above).  */
-      if (__glibc_unlikely (pd->stopped_start))
-	{
-	  /* Get the lock the parent locked to force synchronization.  */
-	  lll_lock (pd->lock, LLL_PRIVATE);
-
-	  /* We have ownership of PD now.  */
-	  if (pd->setup_failed == 1)
-	    {
-	      /* In the case of a failed setup, the created thread will be
-		 responsible to free up the allocated resources.  The
-		 detached mode ensure it won't be joined and it will trigger
-		 the required cleanup.  */
-	      pd->joinid = pd;
-	      __do_cancel ();
-	    }
-
-	  /* And give it up right away.  */
-	  lll_unlock (pd->lock, LLL_PRIVATE);
-	}
-
       LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg);
 
       /* Run the code the user provided.  */
@@ -556,6 +549,7 @@ start_thread (void *arg)
     /* Free the TCB.  */
     __nptl_free_tcb (pd);
 
+out:
   /* We cannot call '_exit' here.  '_exit' will terminate the process.
 
      The 'exit' implementation in the kernel will signal when the
@@ -802,6 +796,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
      thread.  */
   __libc_signal_restore_set (&original_sigmask);
 
+  int setup_failed = 0;
+
   if (__glibc_unlikely (retval != 0))
     {
       if (thread_ran)
@@ -814,7 +810,7 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
   	  /* State (a), we own PD. The thread blocked on this lock will
 	     finish due setup_failed being set.  The thread will be
 	     responsible to cleanup any allocated resource.  */
-	  pd->setup_failed = 1;
+	  setup_failed = pd->setup_failed = 1;
 	  lll_unlock (pd->lock, LLL_PRIVATE);
         }
       else
@@ -857,6 +853,9 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
       THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
     }
 
+  if (setup_failed == 1)
+    __pthread_join (*newthread, NULL);
+
  out:
   if (destroy_default_attr)
     __pthread_attr_destroy (&default_attr.external); 

  reply	other threads:[~2021-06-01 13:55 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-27 17:28 [PATCH v2 0/9] nptl: pthread cancellation refactor Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 1/9] nptl: Remove exit-thread.h Adhemerval Zanella
2021-06-01  7:51   ` Florian Weimer
2021-06-01 12:55     ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 2/9] nptl: Deallocate the thread stack on setup failure (BZ #19511) Adhemerval Zanella
2021-06-01  8:32   ` Florian Weimer
2021-06-01 13:08     ` Adhemerval Zanella
2021-06-01 13:55       ` Adhemerval Zanella [this message]
2021-06-02 12:56   ` [PATCH v3] " Adhemerval Zanella
2021-06-02 13:08     ` Andreas Schwab
2021-06-02 13:39       ` Adhemerval Zanella
2021-06-02 13:41         ` Andreas Schwab
2021-06-02 14:01           ` Adhemerval Zanella
2021-06-02 14:07             ` Andreas Schwab
2021-06-02 14:15               ` Adhemerval Zanella
2021-06-02 14:30                 ` Andreas Schwab
2021-06-02 14:42                   ` Adhemerval Zanella
2021-06-02 18:20               ` Joseph Myers
2021-06-02 18:30                 ` Florian Weimer
2021-06-02 19:02                   ` Adhemerval Zanella
2021-06-02 19:11                     ` Florian Weimer
2021-06-08 10:56     ` Florian Weimer
2021-06-08 17:01       ` Adhemerval Zanella
2021-06-09 13:49         ` Florian Weimer
2021-06-09 17:07           ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 3/9] nptl: Install cancellation handler on pthread_cancel Adhemerval Zanella
2021-05-31 18:18   ` Adhemerval Zanella
2021-06-01  8:38     ` Florian Weimer
2021-06-01 13:10       ` Adhemerval Zanella
2021-06-01  8:39   ` Florian Weimer
2021-05-27 17:28 ` [PATCH v2 4/9] nptl: Remove CANCELING_BITMASK Adhemerval Zanella
2021-06-01  9:03   ` Florian Weimer
2021-06-01 13:50     ` Adhemerval Zanella
2021-06-01 16:36       ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 5/9] nptl: Move cancel state out of cancelhandling Adhemerval Zanella
2021-06-01  9:58   ` Florian Weimer
2021-06-02 13:09     ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 6/9] nptl: Move cancel type " Adhemerval Zanella
2021-06-01 12:37   ` Florian Weimer
2021-06-02 13:11     ` Adhemerval Zanella
2021-06-09 17:06       ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 7/9] nptl: Implement raise in terms of pthread_kill Adhemerval Zanella
2021-06-01 12:40   ` Florian Weimer
2021-06-02 13:14     ` Adhemerval Zanella
2021-05-27 17:28 ` [PATCH v2 8/9] nptl: Use pthread_kill on pthread_cancel Adhemerval Zanella
2021-06-01 12:41   ` Florian Weimer
2021-05-27 17:28 ` [PATCH v2 9/9] nptl: Avoid async cancellation to wrongly update __nptl_nthreads (BZ #19366) Adhemerval Zanella
2021-06-01 14:29   ` Florian Weimer
2021-06-02 13:15     ` Adhemerval Zanella

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6d2dc011-054b-56be-7ba7-9fdd91003bb6@linaro.org \
    --to=adhemerval.zanella@linaro.org \
    --cc=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).