]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl_db/td_thr_validate.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl_db / td_thr_validate.c
index 3d560a621b2032ad29941bc55d6cafcb51376396..f3c8a7bed64ea08740ef84984c180ae7df33ae67 100644 (file)
@@ -1,5 +1,5 @@
 /* Validate a thread handle.
-   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -14,9 +14,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include "thread_dbP.h"
 #include <stdbool.h>
@@ -75,16 +74,33 @@ td_thr_validate (const td_thrhandle_t *th)
       if (err == TD_OK)
        err = check_thread_list (th, list, &uninit);
 
-      if (err == TD_NOTHR && uninit)
+      if (err == TD_NOTHR && uninit && th->th_unique == 0)
+       /* __pthread_initialize_minimal has not run yet.
+          There is only the special case thread handle.  */
+       err = TD_OK;
+    }
+
+  if (err == TD_OK)
+    {
+      /* Verify that this is not a stale element in a fork child.  */
+      pid_t match_pid = ps_getpid (th->th_ta_p->ph);
+      psaddr_t pid;
+      err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, pthread, pid, 0);
+      if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
        {
-         /* __pthread_initialize_minimal has not run yet.
-            But the main thread still has a valid ID.  */
-         td_thrhandle_t main_th;
-         err = td_ta_map_lwp2thr (th->th_ta_p,
-                                  ps_getpid (th->th_ta_p->ph), &main_th);
-         if (err == TD_OK && th->th_unique != main_th.th_unique)
-           err = TD_NOTHR;
+         /* This was a thread that was about to fork, or it is the new sole
+            thread in a fork child.  In the latter case, its tid was stored
+            via CLONE_CHILD_SETTID and so is already the proper child PID.  */
+         if (-(pid_t) (uintptr_t) pid == match_pid)
+           /* It is about to do a fork, but is really still the parent PID.  */
+           pid = (psaddr_t) (uintptr_t) match_pid;
+         else
+           /* It must be a fork child, whose new PID is in the tid field.  */
+           err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique,
+                               pthread, tid, 0);
        }
+      if (err == TD_OK && (pid_t) (uintptr_t) pid != match_pid)
+       err = TD_NOTHR;
     }
 
   return err;