Patch to support Linux threaded programs even better
Ganesan R
rganesan at myrealbox.com
Mon Apr 2 09:55:15 UTC 2001
Wichert,
I don't know if you've already released 4.3, the attached patch fixes some
more problems using strace with multi-threaded programs on Linux. Please
include it in the release if possible.
When I submitted my previous patch, I had commented that strace exits with a
message SIGRT_0 and I couldn't understand what was going on. It turns out
that LinuxThreads uses SIGRTMIN, SIGRTMIN + 1 and SIGRTMIN + 2 internally
for thread restarting, cancellation and debugging internally. My first
attempt at the patch simply handled these as a special case. Then I dug in
further to see *why* these signals didn't appear in the "caught" signals for
the process.
Digging into the kernel sources I found this comment for the /proc/pid/stat
interface.
-- from fs/proc/array.c
/* The signal information here is obsolete.
* It must be decimal for Linux 2.0 compatibility.
* Use /proc/#/status for real-time signals.
*/
-- end snippet
No wonder strace thinks these signals are not handled! The attached patch
parses the /proc/pid/status file instead. Tracing LinuxThreads programs works
much better now.
The only remaining problem is that when strace exits while tracing a
threaded process (for eg when the user hits Ctrl-C), the process is left in
the STOPPED state. This may be a kernel bug, I'll investigate further when I
have some time.
Parsing /proc/#/status every time is going to be a big performance hit for
MT programs, I am planning to work on a patch that caches the information
and re-parse it only when the process makes a signal related syscall.
Meanwhile, the attached patch at least works :-).
Ganesan
--
Ganesan R <rganesan at myrealbox.com> | Ph: 91-422-549 860 (Home)
Novell India, Bangalore | #include <std_disclaimer.h>
-------------- next part --------------
Index: signal.c
===================================================================
RCS file: /cvsroot/strace/strace/signal.c,v
retrieving revision 1.28
diff -u -r1.28 signal.c
--- signal.c 2001/03/28 20:29:17 1.28
+++ signal.c 2001/04/02 09:35:58
@@ -378,40 +378,54 @@
#ifdef LINUX
int sfd;
char sname[32];
- char buf[1024];
+ char buf[2048];
char *s;
int i;
- unsigned int signalled, blocked, ignored, caught;
+ /* We also need to handle RT signals */
+ unsigned long long signalled, blocked, ignored, caught;
/* This is incredibly costly but it's worth it. */
- sprintf(sname, "/proc/%d/stat", tcp->pid);
+ /* NOTE: LinuxThreads internally uses SIGRTMIN, SIGRTMIN + 1 and
+ SIGRTMIN + 2, so we can't use the obsolete /proc/%d/stat which
+ doesn't handle real-time signals). */
+ sprintf(sname, "/proc/%d/status", tcp->pid);
if ((sfd = open(sname, O_RDONLY)) == -1) {
perror(sname);
return 1;
}
- i = read(sfd, buf, 1024);
+ i = read(sfd, buf, sizeof(buf));
buf[i] = '\0';
close(sfd);
/*
- * Skip the extraneous fields. This loses if the
+ * Skip the extraneous fields. We need to skip
* command name has any spaces in it. So be it.
*/
- for (i = 0, s = buf; i < 30; i++) {
- while (*++s != ' ') {
- if (!*s)
- break;
- }
- }
- if (sscanf(s, "%u%u%u%u",
- &signalled, &blocked, &ignored, &caught) != 4) {
- fprintf(stderr, "/proc/pid/stat format error\n");
+ s = strstr(buf, "SigPnd:\t");
+
+ if (!s)
+ {
+ fprintf(stderr, "/proc/pid/status format error\n");
return 1;
}
+
+ while (*s && *s++ != '\t')
+ ;
+ s += sscanf(s, "%qx", &signalled);
+ while (*s && *s++ != '\t')
+ ;
+ s += sscanf(s, "%qx", &blocked);
+ while (*s && *s++ != '\t')
+ ;
+ s += sscanf(s, "%qx", &ignored);
+ while (*s && *s++ != '\t')
+ ;
+ s += sscanf(s, "%qx", &caught);
+
#ifdef DEBUG
fprintf(stderr, "sigs: %08x %08x %08x %08x\n",
signalled, blocked, ignored, caught);
#endif
- if ((ignored & sigmask(sig)) || (caught & sigmask(sig)))
+ if ((ignored & (1ULL << sig)) || (caught & (1ULL << sig)))
return 1;
#endif /* LINUX */
More information about the Strace-devel
mailing list