strace fails to trace call stack of clone from pthread_create
Masatake YAMATO
yamato at redhat.com
Fri Nov 2 06:49:20 UTC 2018
> Hi everyone,
>
> I find strace fails to trace call stack of clone syscall (called by
> pthread_create) in both main thread and child thread.
>
> How to reproduce:
>
> Get a simple pthread_create example:
> http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
> Compile: gcc -pthread test_pthread.c -o test_pthread
> Trace: strace -k -ff -o test_pthread ./test_pthread
>
> In main thread:
> clone(child_stack=0x7f56c52b1ff0,
> flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
> parent_tidptr=0x7f56c52b29d0, tls=0x7f56c52b2700,
> child_tidptr=0x7f56c52b29d0) = 69700
> > /lib/x86_64-linux-gnu/libc-2.23.so(clone+0x31) [0x1073e1]
>
> In child thread:
> set_robust_list(0x7f56c52b29e0, 24) = 0
> > /lib/x86_64-linux-gnu/libpthread-2.23.so(start_thread+0x64) [0x7654]
> > /lib/x86_64-linux-gnu/libc-2.23.so(clone+0x6d) [0x10741d]
>
> We can see the call stacks of both main thread and child thread start from
> libc. Is there any way to get the call stack from the main function? I'm
> not sure whether this is a bug or not.
It looks a bug.
About the most of all system calls, strace captures its stack trace after
kernel executes the system call. However, about some system calls, caputirng
after executing is not useful. I put makers "SE" on such a system call in
syscallent.h. SE is defined as STACKTRACE_CAPTURE_ON_ENTER in code.
I put SE markers on execve and _exit for exapmles.
I should put the maker on clone, fork, and vfrok, too.
Before writing this mail, I expected the bug you reported will be fixed by putting
the marker on the system calls like:
diff --git a/linux/x86_64/syscallent.h b/linux/x86_64/syscallent.h
index 63ec52e8..2be891bd 100644
--- a/linux/x86_64/syscallent.h
+++ b/linux/x86_64/syscallent.h
@@ -54,9 +54,9 @@
[ 53] = { 4, TN, SEN(socketpair), "socketpair" },
[ 54] = { 5, TN, SEN(setsockopt), "setsockopt" },
[ 55] = { 5, TN, SEN(getsockopt), "getsockopt" },
-[ 56] = { 5, TP, SEN(clone), "clone" },
-[ 57] = { 0, TP, SEN(fork), "fork" },
-[ 58] = { 0, TP, SEN(vfork), "vfork" },
+[ 56] = { 5, TP|SE, SEN(clone), "clone" },
+[ 57] = { 0, TP|SE, SEN(fork), "fork" },
+[ 58] = { 0, TP|SE, SEN(vfork), "vfork" },
[ 59] = { 3, TF|TP|SE|SI, SEN(execve), "execve" },
[ 60] = { 1, TP|SE, SEN(exit), "exit" },
[ 61] = { 4, TP, SEN(wait4), "wait4" },
However, though I put the maker on them, I cannot get expected result
either using libunwind or libdw.
I read the implemention of the wrapper for clone systecall.
It is not written in C but in x86-64 Assembly language.
So I guess the frame structure(?) that the unwinder expects are
not constructed when executing clone syscall. So unwinder
cannot capture a stack trace in the context.
I have to take much more time for understanding the issue.
Masatake YAMATO
> Thanks,
> Zhouyang
More information about the Strace-devel
mailing list