From patchwork Fri Sep 29 12:12:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 23227 Received: (qmail 15253 invoked by alias); 29 Sep 2017 12:20:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 14979 invoked by uid 89); 29 Sep 2017 12:20:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=south, clone X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Sep 2017 12:20:09 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F2FA2C057F91 for ; Fri, 29 Sep 2017 12:12:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F2FA2C057F91 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=palves@redhat.com Received: from cascais.lan (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 64336183CF for ; Fri, 29 Sep 2017 12:12:27 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [pushed 1/2] Fix gdbserver regression exposed by gdb.threads/multi-create-ns-info-thr.exp Date: Fri, 29 Sep 2017 13:12:25 +0100 Message-Id: <1506687146-31225-1-git-send-email-palves@redhat.com> Commit 8629910955a7 ("Add thread_db_notice_clone to gdbserver") introduced calls into libthread_db without making sure that the current thread is pointing to a know-stopped thread. This resulted in sometimes thread_db_notice_clone failing->find_one_thread failing like this, as seen when running gdb.threads/multi-create-ns-info-thr.exp: ~~~ Thread <6> executing Thread <7> executing gdbserver: PID mismatch! Expected 27472, got 27471 gdbserver: Cannot find thread after clone. Thread <1000> executing Thread <1001> executing ~~~ Things go south from here and sometimes that ends up resulting in gdbserver crashing and the test failing. gdb/gdbserver/ChangeLog: 2017-09-29 Pedro Alves * linux-low.c (handle_extended_wait): Pass parent thread instead of process to thread_db_notice_clone. * linux-low.h (thread_db_notice_clone): Replace parent process parameter with parent thread parameter. * thread-db.c (find_one_thread): Add comment. (thread_db_notice_clone): Replace parent process parameter with parent thread parameter. Temporarily switch to the parent thread. --- gdb/gdbserver/ChangeLog | 10 ++++++++++ gdb/gdbserver/linux-low.c | 2 +- gdb/gdbserver/linux-low.h | 2 +- gdb/gdbserver/thread-db.c | 17 ++++++++++++++--- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 63fb653..f27451d 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,13 @@ +2017-09-29 Pedro Alves + + * linux-low.c (handle_extended_wait): Pass parent thread instead + of process to thread_db_notice_clone. + * linux-low.h (thread_db_notice_clone): Replace parent process + parameter with parent thread parameter. + * thread-db.c (find_one_thread): Add comment. + (thread_db_notice_clone): Replace parent process parameter with + parent thread parameter. Temporarily switch to the parent thread. + 2017-09-26 Sergio Durigan Junior * gdbthread.h: Include "common-gdbthread.h". diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index c62dc19..54005c1 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -656,7 +656,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) new_lwp->status_pending = status; } - thread_db_notice_clone (get_thread_process (event_thr), ptid); + thread_db_notice_clone (event_thr, ptid); /* Don't report the event. */ return 1; diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 85bb8ca..0ece7bc 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -417,7 +417,7 @@ int thread_db_look_up_one_symbol (const char *name, CORE_ADDR *addrp); both the clone and the parent should be stopped. This function does whatever is required have the clone under thread_db's control. */ -void thread_db_notice_clone (struct process_info *proc, ptid_t lwp); +void thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid); bool thread_db_thread_handle (ptid_t ptid, gdb_byte **handle, int *handle_len); diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c index 9156d89..638a833 100644 --- a/gdb/gdbserver/thread-db.c +++ b/gdb/gdbserver/thread-db.c @@ -28,6 +28,7 @@ extern int debug_threads; #include "nat/gdb_thread_db.h" #include "gdb_vecs.h" #include "nat/linux-procfs.h" +#include "common/scoped_restore.h" #ifndef USE_LIBTHREAD_DB_DIRECTLY #include @@ -155,6 +156,9 @@ thread_db_state_str (td_thr_state_e state) } #endif +/* Get thread info about PTID, accessing memory via the current + thread. */ + static int find_one_thread (ptid_t ptid) { @@ -887,15 +891,22 @@ thread_db_handle_monitor_command (char *mon) /* See linux-low.h. */ void -thread_db_notice_clone (struct process_info *proc, ptid_t ptid) +thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid) { - struct thread_db *thread_db = proc->priv->thread_db; + process_info *parent_proc = get_thread_process (parent_thr); + struct thread_db *thread_db = parent_proc->priv->thread_db; /* If the thread layer isn't initialized, return. It may just be that the program uses clone, but does not use libthread_db. */ if (thread_db == NULL || !thread_db->all_symbols_looked_up) return; - if (!find_one_thread (ptid)) + /* find_one_thread calls into libthread_db which accesses memory via + the current thread. Temporarily switch to a thread we know is + stopped. */ + scoped_restore restore_current_thread + = make_scoped_restore (¤t_thread, parent_thr); + + if (!find_one_thread (child_ptid)) warning ("Cannot find thread after clone.\n"); }