From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id IKx9Lt6+/GUI2RAAWB0awg (envelope-from ) for ; Thu, 21 Mar 2024 19:12:30 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=laS3ar0Z; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id B8C8E1E0C0; Thu, 21 Mar 2024 19:12:30 -0400 (EDT) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 9FCE01E0BB for ; Thu, 21 Mar 2024 19:12:28 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3EEA03858C35 for ; Thu, 21 Mar 2024 23:12:28 +0000 (GMT) Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by sourceware.org (Postfix) with ESMTPS id 319693858403 for ; Thu, 21 Mar 2024 23:12:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 319693858403 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 319693858403 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::635 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711062726; cv=none; b=K8mrCEBDBLCevBTv9u1nGSi8LeAarWTVzQKy0EjZ2p16GR/JSHldUVynYx0ER65sP8HTIOrJQi31SnCF9E8DfFy40IDI8JsAnJH/Zm8wJnzEPGZ/Z0Siutq6pQOHH2QnF63ZEPSzy9Ju6dmByuQgK+CrTTBM07k4Rw1Xwird+Xk= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711062726; c=relaxed/simple; bh=818FEv4/frxkFsGU1SsjCA0NgV1W90ucluEEANX2nH4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=kw3ES8nyl/OsfogtfcUXcBmZfYml+z2YuSXXVCAoh8mdy50lZd5eKnwP8xq1fnZTuITVvGSMFAHgJa/pz6uqqHdx7rWedhS4vR6GIt52Sp5Z4Rg5NZGH9zmyLsc73+1T5EQJt7bJCOa89kq+8VrwkAU8155cCYkfztuasQ5cSus= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1df01161b39so11676355ad.3 for ; Thu, 21 Mar 2024 16:12:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1711062722; x=1711667522; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=a+Z4bhIfz3C2lA0gF6f2QF56TZJlgwzNAgggQlmVHTY=; b=laS3ar0ZGVQlZboUAKkaE0mnk71i7sFQ4XKWLOMIZqXsU5c3/JXVbD6jpky7ZN0X4L 4iMi0b4f+k+Va0RCc5rWlvzwRMPgUbkEisxzfoUwGuGJmjFuS5tVwehELdUZ2b7SsIcu M7yo99QFVWIxoqATwjjR+k8i19cVFGRta43hxWWngvON8zPs30qClnwRmmmtCQG3llOq Ym83estK36tiS73Y3P9/ytnwluD+0wp58WoBb0Zhzeht+xieybrN49o6aLWyYYAeEBbf DsD8FEOBLYDmPsDle540ccHws7TBE0dVZepooodzeLuxCgYy/oi+0GkZsnDhCvy1SkFX kpcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711062722; x=1711667522; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=a+Z4bhIfz3C2lA0gF6f2QF56TZJlgwzNAgggQlmVHTY=; b=FMj+Co9SaLRouaKKeEtr2VbalNjQK/BCsS00lxwGycbuyXoiC5e4cc+DyXf95OFy14 mNUDDICM9hkw5KMFko3G0qZuUR4MOKi3Cvx3sTkmauY9/8tWGRi3CBYHHKIngaJP6OXR s6vIyAJHqIiPLlGPF4HJ7GbUmVZ/laqkUHqkK8nBEH5hjIvePAn+a/OF+BHkTIOvPP3R PjC6v1HKBeQHCCucOjqKtx59HjoE6ASvzoCxZO3WnkAfw/9atvkuVEn3UwtP2vtCU0dn Rfsx/ntyGG7vVlw9FqlBAP0XHTt4H2sBPxE0dWuqt3jFIlCs6+GUZl2yLXMNb0f59WP9 UuUw== X-Gm-Message-State: AOJu0YwHTbSbTcqgHuNpWiO+xBjs5FjmcNtX+S9809uxJHFgH27Pxoqk GVxuh2ueHDpkJg5orMtpPwuyneauf8FWSvK/LQ/S7W23UprowqsZdhdBhq/niPdT7Nu4kBMsKA9 x X-Google-Smtp-Source: AGHT+IERhYuI3QdtojUniixlSXaa6wXa7Cp8Y2YGyTx3XXC8MroJ3pnzYHLmijmYl/QxSZlUQg59NA== X-Received: by 2002:a17:903:2609:b0:1e0:2a5f:5e21 with SMTP id jd9-20020a170903260900b001e02a5f5e21mr940890plb.26.1711062722111; Thu, 21 Mar 2024 16:12:02 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:e28:f7d5:8d63:c544]) by smtp.gmail.com with ESMTPSA id i17-20020a17090332d100b001dd922cbb58sm417977plr.62.2024.03.21.16.12.01 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Mar 2024 16:12:01 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH 3/3] gdb/nat/linux: Fix attaching to process when it has zombie threads Date: Thu, 21 Mar 2024 20:11:49 -0300 Message-ID: <20240321231149.519549-4-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20240321231149.519549-1-thiago.bauermann@linaro.org> References: <20240321231149.519549-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org When GDB attaches to a multi-threaded process, it calls linux_proc_attach_tgid_threads () to go through all threads found in /proc/PID/task/ and call attach_proc_task_lwp_callback () on each of them. If it does that twice without the callback reporting that a new thread was found, then it considers that all inferior threads have been found and returns. The problem is that the callback considers any thread that it hasn't attached to yet as new. This causes problems if the process has one or more zombie threads, because GDB can't attach to it and the loop will always "find" a new thread (the zombie one), and get stuck in an infinite loop. This is easy to trigger (at least on aarch64-linux and powerpc64le-linux) with the gdb.threads/attach-many-short-lived-threads.exp testcase, because its test program constantly creates and finishes joinable threads so the chance of having zombie threads is high. This problem causes the following failures: FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: attach (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: no new threads (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: set breakpoint always-inserted on (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: break break_fn (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: break at break_fn: 1 (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: break at break_fn: 2 (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: break at break_fn: 3 (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: reset timer in the inferior (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: print seconds_left (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: detach (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: set breakpoint always-inserted off (timeout) FAIL: gdb.threads/attach-many-short-lived-threads.exp: iter 8: delete all breakpoints, watchpoints, tracepoints, and catchpoints in delete_breakpoints (timeout) ERROR: breakpoints not deleted The iteration number is random, and all tests in the subsequent iterations fail too, because GDB is stuck in the attach command at the beginning of the iteration. The solution is to make linux_proc_attach_tgid_threads () remember when it has already processed a given LWP and skip it in the subsequent iterations. PR testsuite/31312 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31312 --- gdb/nat/linux-osdata.c | 22 ++++++++++++++++++++++ gdb/nat/linux-osdata.h | 4 ++++ gdb/nat/linux-procfs.c | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c index c254f2e4f05b..998279377433 100644 --- a/gdb/nat/linux-osdata.c +++ b/gdb/nat/linux-osdata.c @@ -112,6 +112,28 @@ linux_common_core_of_thread (ptid_t ptid) return core; } +/* See linux-osdata.h. */ + +std::optional +linux_get_starttime (ptid_t ptid) +{ + std::optional field = linux_find_proc_stat_field (ptid, 22); + + if (!field.has_value ()) + return {}; + + errno = 0; + const char *trailer; + ULONGEST starttime = strtoulst (field->c_str (), &trailer, 10); + if (starttime == ULONGEST_MAX && errno == ERANGE) + return {}; + else if (*trailer != '\0') + /* There were unexpected characters. */ + return {}; + + return starttime; +} + /* Finds the command-line of process PID and copies it into COMMAND. At most MAXLEN characters are copied. If the command-line cannot be found, PID is copied into command in text-form. */ diff --git a/gdb/nat/linux-osdata.h b/gdb/nat/linux-osdata.h index a82fb08b998e..1cdc687aa9cf 100644 --- a/gdb/nat/linux-osdata.h +++ b/gdb/nat/linux-osdata.h @@ -27,4 +27,8 @@ extern int linux_common_core_of_thread (ptid_t ptid); extern LONGEST linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, ULONGEST offset, ULONGEST len); +/* Get the start time of thread PTID. */ + +extern std::optional linux_get_starttime (ptid_t ptid); + #endif /* NAT_LINUX_OSDATA_H */ diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c index b17e3120792e..b01bf36c0b53 100644 --- a/gdb/nat/linux-procfs.c +++ b/gdb/nat/linux-procfs.c @@ -17,10 +17,13 @@ along with this program. If not, see . */ #include "gdbsupport/common-defs.h" +#include "linux-osdata.h" #include "linux-procfs.h" #include "gdbsupport/filestuff.h" #include #include +#include +#include /* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not found. */ @@ -290,6 +293,10 @@ linux_proc_attach_tgid_threads (pid_t pid, return; } + /* Keeps track of the LWPs we have already visited in /proc, + identified by their PID and starttime to detect PID reuse. */ + std::set> visited_lwps; + /* Scan the task list for existing threads. While we go through the threads, new threads may be spawned. Cycle through the list of threads until we have done two iterations without finding new @@ -308,6 +315,18 @@ linux_proc_attach_tgid_threads (pid_t pid, if (lwp != 0) { ptid_t ptid = ptid_t (pid, lwp); + std::optional starttime = linux_get_starttime (ptid); + + if (starttime.has_value ()) + { + std::pair key (lwp, *starttime); + + /* If we already visited this LWP, skip it this time. */ + if (visited_lwps.find (key) != visited_lwps.cend ()) + continue; + + visited_lwps.insert (key); + } if (attach_lwp (ptid)) new_threads_found = 1;