From patchwork Mon Nov 23 10:49:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 9779 Received: (qmail 72909 invoked by alias); 23 Nov 2015 10:50:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 72875 invoked by uid 89); 23 Nov 2015 10:50:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com From: Gary Benson To: libc-alpha@sourceware.org Subject: [PATCH 2/2] Improve td_ta_thr_iter main thread faking logic Date: Mon, 23 Nov 2015 10:49:55 +0000 Message-Id: <1448275795-6283-3-git-send-email-gbenson@redhat.com> In-Reply-To: <1448275795-6283-1-git-send-email-gbenson@redhat.com> References: <1448275795-6283-1-git-send-email-gbenson@redhat.com> Currently td_ta_thr_iter fakes a special descriptor for the main thread if __stack_user == NULL. This leaves a tiny window between __stack_user being initialized and the main thread being added during which td_ta_thr_iter will fail to call the callback. This commit updates the main thread faking logic to fake the main thread if both __stack_user and stack_used are either NULL or empty. (It's not sufficient to key this only to __stack_user because __reclaim_stacks can add the main thread to stack_used in which case __stack_user will be empty but the main thread should not be faked). --- nptl_db/td_ta_thr_iter.c | 32 +++++++++++++++++++++----------- 1 files changed, 21 insertions(+), 11 deletions(-) diff --git a/nptl_db/td_ta_thr_iter.c b/nptl_db/td_ta_thr_iter.c index f79a902..5d54aa4 100644 --- a/nptl_db/td_ta_thr_iter.c +++ b/nptl_db/td_ta_thr_iter.c @@ -23,7 +23,7 @@ static td_err_e iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, void *cbdata_p, td_thr_state_e state, int ti_pri, - psaddr_t head, bool fake_empty, pid_t match_pid) + psaddr_t head, int *empty_count, pid_t match_pid) { td_err_e err; psaddr_t next, ofs; @@ -38,15 +38,11 @@ iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, if (err != TD_OK) return err; - if (next == 0 && fake_empty) + if (next == 0 || next == head) { - /* __pthread_initialize_minimal has not run. There is just the main - thread to return. We cannot rely on its thread register. They - sometimes contain garbage that would confuse us, left by the - kernel at exec. So if it looks like initialization is incomplete, - we only fake a special descriptor for the initial thread. */ - td_thrhandle_t th = { ta, 0 }; - return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK; + /* The list is uninitialized or empty. */ + (*empty_count)++; + return TD_OK; } /* Cache the offset from struct pthread to its list_t member. */ @@ -139,6 +135,7 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, td_thragent_t *const ta = (td_thragent_t *) ta_arg; td_err_e err; psaddr_t list = 0; + int empty_count = 0; LOG ("td_ta_thr_iter"); @@ -157,14 +154,27 @@ td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, err = DB_GET_SYMBOL (list, ta, __stack_user); if (err == TD_OK) err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, - list, true, pid); + list, &empty_count, pid); /* And the threads with stacks allocated by the implementation. */ if (err == TD_OK) err = DB_GET_SYMBOL (list, ta, stack_used); if (err == TD_OK) err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, - list, false, pid); + list, &empty_count, pid); + + if (err == TD_OK && empty_count == 2) + { + /* __pthread_initialize_minimal has not completed. We need to + call the callback for the main thread, but we cannot rely on + its thread register (they sometimes contain garbage that + would confuse us, left by the kernel at exec) so we fake a + special descriptor for the initial thread. */ + td_thrhandle_t th = { ta, 0 }; + + if (callback (&th, cbdata_p) != 0) + err = TD_DBERR; + } return err; }