public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
From: Jan Kratochvil <jan.kratochvil@redhat.com>
To: elfutils-devel@lists.fedorahosted.org
Subject: Re: [PATCH] Add --core-pattern option to eu-stack
Date: Wed, 26 Nov 2014 15:32:39 +0100	[thread overview]
Message-ID: <20141126143239.GA16611@host2.jankratochvil.net> (raw)
In-Reply-To: 1414706141.18323.39.camel@bordewijk.wildebeest.org

[-- Attachment #1: Type: text/plain, Size: 5281 bytes --]

On Thu, 30 Oct 2014 22:55:41 +0100, Mark Wielaard wrote:
> On Thu, 2014-10-09 at 23:25 +0200, Jan Kratochvil wrote:
> > +      if (opt_core_pattern == true && show_one_tid == false)
> > +	argp_error (state,
> > +		    N_("--core-pattern requires -1"));
> 
> Why this restriction?

I was blindly following Oleg's note which was not so obvious to me, though:

On Wed, 03 Sep 2014 16:26:41 +0200, Oleg Nesterov wrote:
# Obviously, this way you can only inspect the thread which dumps the core.

Therefore I have now tried to remove this limitation of
  -1                         Show the backtrace of only one thread

But I have found the other threads end up with:
	wait4(13902, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], __WALL, NULL) = 13902

Therefore they are dead at the core_pattern time, they cannot be ptraced and
therefore they cannot be unwound.  One could only find them in the core file
itself but that is outside of the scope of this eu-stack feature.


Jan

diff --git a/src/stack.c b/src/stack.c
index 59ae826..6a8a3ee 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -28,11 +28,16 @@
 #include <fcntl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
+#include <dirent.h>
 #include ELFUTILS_HEADER(dwfl)
 
 #include <dwarf.h>
 #include <system.h>
 
+#ifndef PTRACE_EVENT_STOP
+# define PTRACE_EVENT_STOP 128
+#endif
+
 /* Name and version of program.  */
 static void print_version (FILE *stream, struct argp_state *state);
 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
@@ -480,6 +485,74 @@ print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
   fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
 }
 
+/* Attach thread TID without waiting for it.  It must not be a crashed thread
+   core_pattern has been called for.  */
+
+static void
+core_pattern_seize_one (pid_t tid)
+{
+  if (ptrace (PTRACE_SEIZE, tid, NULL, NULL) != 0)
+    error (EXIT_BAD, errno, "ptrace (PTRACE_SEIZE, %d)", tid);
+  if (ptrace (PTRACE_INTERRUPT, tid, NULL, NULL) != 0)
+    error (EXIT_BAD, errno, "ptrace (PTRACE_INTERRUPT, %d)", tid);
+}
+
+/* Wait for thread TID.  It must not be a crashed thread core_pattern has been
+   called for.  */
+
+static void
+core_pattern_wait_for_one (pid_t tid)
+{
+  int status;
+  if (waitpid (tid, &status, __WALL) != tid)
+    error (EXIT_BAD, errno, "waitpid (%d, __WALL)", tid);
+  if (! WIFSIGNALED (status))
+    error (EXIT_BAD, 0, "waitpid (%d, __WALL) status 0x%x is not WIFSIGNALED",
+           tid, status);
+}
+
+/* Call CB for all threads of process EXCEPT_TID except tid EXCEPT_TID.
+   EXCEPT_TID does not have to be thread group leader.  */
+
+static void
+core_pattern_attach_other (pid_t except_tid, void (*cb) (pid_t tid))
+{
+  char dirname[64];
+  int i = snprintf (dirname, sizeof (dirname), "/proc/%d/task", except_tid);
+  assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
+  DIR *dir = opendir (dirname);
+  if (dir == NULL)
+    error (EXIT_BAD, errno, "opendir (\"%s\")", dirname);
+  for (;;)
+    {
+      errno = 0;
+      struct dirent *dirent = readdir (dir);
+      if (dirent == NULL)
+	{
+	  if (errno != 0)
+	    error (EXIT_BAD, errno, "readdir (\"%s\")", dirname);
+	  break;
+	}
+      if (strcmp (dirent->d_name, ".") == 0
+	  || strcmp (dirent->d_name, "..") == 0)
+	continue;
+      char *end;
+      errno = 0;
+      long tidl = strtol (dirent->d_name, &end, 10);
+      if (errno != 0)
+	error (EXIT_BAD, errno, "strtol (\"%s\"->\"%s\")", dirname,
+	       dirent->d_name);
+      pid_t tid = tidl;
+      if (tidl <= 0 || (end && *end) || tid != tidl)
+	error (EXIT_BAD, 0, "Invalid TID (\"%s\"->\"%s\")", dirname,
+	       dirent->d_name);
+      if (tid != except_tid)
+	cb (tid);
+    }
+  if (closedir (dir) != 0)
+    error (EXIT_BAD, errno, "closedir (\"%s\")", dirname);
+}
+
 /* Provide PTRACE_ATTACH like operation compatible with Linux core_pattern
    handler.  */
 
@@ -489,10 +562,12 @@ core_pattern (void)
   if (ptrace (PTRACE_SEIZE, pid, NULL, (void *) (uintptr_t) PTRACE_O_TRACEEXIT)
       != 0)
     error (EXIT_BAD, errno, "ptrace (PTRACE_SEIZE, PTRACE_O_TRACEEXIT)");
+  if (! show_one_tid)
+    core_pattern_attach_other (pid, core_pattern_seize_one);
   if (close (0) != 0)
     error (EXIT_BAD, errno, "close (0; core file fd)");
   int status;
-  pid_t got = waitpid (pid, &status, 0);
+  pid_t got = waitpid (pid, &status, __WALL);
   if (got == -1)
     error (EXIT_BAD, errno, "waitpid ()");
   if (got != pid)
@@ -507,6 +582,8 @@ core_pattern (void)
 	   "waitpid () returned status 0x%x but (status >> 8)"
 	   " == (SIGTRAP | (PTRACE_EVENT_EXIT << 8)) was expected",
 	   status);
+  if (! show_one_tid)
+    core_pattern_attach_other (pid, core_pattern_wait_for_one);
 }
 
 static error_t
@@ -610,10 +687,6 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
 	argp_error (state,
 		    N_("One of -p PID or --core COREFILE should be given."));
 
-      if (opt_core_pattern == true && show_one_tid == false)
-	argp_error (state,
-		    N_("--core-pattern requires -1"));
-
       if (pid != 0)
 	{
 	  dwfl = dwfl_begin (&proc_callbacks);

             reply	other threads:[~2014-11-26 14:32 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-26 14:32 Jan Kratochvil [this message]
  -- strict thread matches above, loose matches on Subject: below --
2014-11-28 15:04 Mark Wielaard
2014-11-28 14:44 Mark Wielaard
2014-11-28 14:27 Mark Wielaard
2014-11-27 21:47 Jan Kratochvil
2014-11-27 21:41 Jan Kratochvil
2014-11-27 21:27 Jan Kratochvil
2014-11-27 11:17 Mark Wielaard
2014-11-27 11:05 Mark Wielaard
2014-11-27 11:04 Mark Wielaard
2014-11-26 20:57 Oleg Nesterov
2014-11-26 20:26 Jan Kratochvil
2014-11-26 20:08 Oleg Nesterov
2014-11-26 14:47 Jan Kratochvil
2014-11-26 14:44 Jan Kratochvil
2014-11-03 13:22 Mark Wielaard
2014-10-30 21:55 Mark Wielaard

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=20141126143239.GA16611@host2.jankratochvil.net \
    --to=jan.kratochvil@redhat.com \
    --cc=elfutils-devel@lists.fedorahosted.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).