<div dir="ltr"><div dir="ltr"><div>Actually, I didn't pass anything special to fork(3) or pthread_create(3).</div><div dir="ltr">The source code is as follows:<div><br></div><div><br></div><div><div>$ cat test_fork.c</div><div><br></div><div>#include  <stdio.h></div><div>#include  <sys/types.h></div><div><br></div><div>#define   MAX_COUNT  200</div><div><br></div><div>void  ChildProcess(void);</div><div>void  ParentProcess(void);</div><div><br></div><div>void  main(void)</div><div>{</div><div>     pid_t  pid;</div><div><br></div><div>     pid = fork();</div><div>     if (pid == 0) </div><div>          ChildProcess();</div><div>     else </div><div>          ParentProcess();</div><div>}</div><div><br></div><div>void  ChildProcess(void)</div><div>{</div><div>     int   i;</div><div><br></div><div>     for (i = 1; i <= MAX_COUNT; i++)</div><div>          printf("   This line is from child, value = %d\n", i);</div><div>     printf("   *** Child process is done ***\n");</div><div>}</div><div><br></div><div>void  ParentProcess(void)</div><div>{</div><div>     int   i;</div><div><br></div><div>     for (i = 1; i <= MAX_COUNT; i++)</div><div>          printf("This line is from parent, value = %d\n", i);</div><div>     printf("*** Parent is done ***\n");</div><div>}</div><div><br></div><div><br></div><div><br></div><div>$ cat test_pthread.c</div><div>#include <stdio.h></div><div>#include <stdlib.h></div><div>#include <pthread.h></div><div><br></div><div>void *print_message_function( void *ptr );</div><div><br></div><div>int main()</div><div>{</div><div>     pthread_t thread1, thread2;</div><div>     const char *message1 = "Thread 1";</div><div>     const char *message2 = "Thread 2";</div><div>     int  iret1, iret2;</div><div><br></div><div>    /* Create independent threads each of which will execute function */</div><div><br></div><div>     iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);</div><div>     if(iret1)</div><div>     {</div><div>         fprintf(stderr,"Error - pthread_create() return code: %d\n",iret1);</div><div>         exit(EXIT_FAILURE);</div><div>     }</div><div><br></div><div>     iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);</div><div>     if(iret2)</div><div>     {</div><div>         fprintf(stderr,"Error - pthread_create() return code: %d\n",iret2);</div><div>         exit(EXIT_FAILURE);</div><div>     }</div><div><br></div><div>     printf("pthread_create() for thread 1 returns: %d\n",iret1);</div><div>     printf("pthread_create() for thread 2 returns: %d\n",iret2);</div><div><br></div><div>     /* Wait till threads are complete before main continues. Unless we  */</div><div>     /* wait we run the risk of executing an exit which will terminate   */</div><div>     /* the process and all threads before the threads have completed.   */</div><div><br></div><div>     pthread_join( thread1, NULL);</div><div>     pthread_join( thread2, NULL); </div><div><br></div><div>     exit(EXIT_SUCCESS);</div><div><br></div><div>     return 0;</div><div>}</div><div><br></div><div>void *print_message_function( void *ptr )</div><div>{</div><div>     char *message;</div><div>     message = (char *) ptr;</div><div>     printf("%s \n", message);</div><div>}</div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Sun, Nov 4, 2018 at 1:44 PM Masatake YAMATO <<a href="mailto:yamato@redhat.com">yamato@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fri, 2 Nov 2018 09:46:06 -0400, Zhouyang Jia <<a href="mailto:jiazhouyang09@gmail.com" target="_blank">jiazhouyang09@gmail.com</a>> wrote:<br>
> FYI, I also found clone(2) from fork(3) works fine, while clone(2)<br>
> from pthread_create(3) has the bug.<br>
> So, I guess the problem might be caused by thread mechanism.<br>
<br>
Interesting. I'd like to see your source code of program for testing<br>
clone(2).<br>
<br>
       int clone(int (*fn)(void *), void *child_stack,<br>
                 int flags, void *arg, ...<br>
                 /* pid_t *ptid, void *newtls, pid_t *ctid */ );<br>
<br>
I wonder what you passed to `child_stack'.<br>
<br>
Masatake YAMATO<br>
<br>
> Best,<br>
> Zhouyang<br>
> <br>
> On Fri, Nov 2, 2018 at 2:49 AM Masatake YAMATO <<a href="mailto:yamato@redhat.com" target="_blank">yamato@redhat.com</a>> wrote:<br>
> <br>
>> > Hi everyone,<br>
>> ><br>
>> > I find strace fails to trace call stack of clone syscall (called by<br>
>> > pthread_create) in both main thread and child thread.<br>
>> ><br>
>> > How to reproduce:<br>
>> ><br>
>> > Get a simple pthread_create example:<br>
>> > <a href="http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html" rel="noreferrer" target="_blank">http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html</a><br>
>> > Compile: gcc -pthread test_pthread.c -o test_pthread<br>
>> > Trace: strace -k -ff -o test_pthread ./test_pthread<br>
>> ><br>
>> > In main thread:<br>
>> >     clone(child_stack=0x7f56c52b1ff0,<br>
>> ><br>
>> flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,<br>
>> > parent_tidptr=0x7f56c52b29d0, tls=0x7f56c52b2700,<br>
>> > child_tidptr=0x7f56c52b29d0) = 69700<br>
>> >      > /lib/x86_64-linux-gnu/<a href="http://libc-2.23.so" rel="noreferrer" target="_blank">libc-2.23.so</a>(clone+0x31) [0x1073e1]<br>
>> ><br>
>> > In child thread:<br>
>> >     set_robust_list(0x7f56c52b29e0, 24) = 0<br>
>> >      > /lib/x86_64-linux-gnu/<a href="http://libpthread-2.23.so" rel="noreferrer" target="_blank">libpthread-2.23.so</a>(start_thread+0x64)<br>
>> [0x7654]<br>
>> >      > /lib/x86_64-linux-gnu/<a href="http://libc-2.23.so" rel="noreferrer" target="_blank">libc-2.23.so</a>(clone+0x6d) [0x10741d]<br>
>> ><br>
>> > We can see the call stacks of both main thread and child thread start<br>
>> from<br>
>> > libc. Is there any way to get the call stack from the main function? I'm<br>
>> > not sure whether this is a bug or not.<br>
>><br>
>> It looks a bug.<br>
>><br>
>> About the most of all system calls, strace captures its stack trace after<br>
>> kernel executes the system call. However, about some system calls,<br>
>> caputirng<br>
>> after executing is not useful. I put makers "SE" on such a system call in<br>
>> syscallent.h. SE is defined as STACKTRACE_CAPTURE_ON_ENTER in code.<br>
>> I put SE markers on execve and _exit for exapmles.<br>
>><br>
>> I should put the maker on clone, fork, and vfrok, too.<br>
>> Before writing this mail, I expected the bug you reported will be fixed by<br>
>> putting<br>
>> the marker on the system calls like:<br>
>><br>
>> diff --git a/linux/x86_64/syscallent.h b/linux/x86_64/syscallent.h<br>
>> index 63ec52e8..2be891bd 100644<br>
>> --- a/linux/x86_64/syscallent.h<br>
>> +++ b/linux/x86_64/syscallent.h<br>
>> @@ -54,9 +54,9 @@<br>
>>  [ 53] = { 4,   TN,             SEN(socketpair),<br>
>> "socketpair"            },<br>
>>  [ 54] = { 5,   TN,             SEN(setsockopt),<br>
>> "setsockopt"            },<br>
>>  [ 55] = { 5,   TN,             SEN(getsockopt),<br>
>> "getsockopt"            },<br>
>> -[ 56] = { 5,   TP,             SEN(clone),                     "clone"<br>
>>              },<br>
>> -[ 57] = { 0,   TP,             SEN(fork),                      "fork"<br>
>>               },<br>
>> -[ 58] = { 0,   TP,             SEN(vfork),                     "vfork"<br>
>>              },<br>
>> +[ 56] = { 5,   TP|SE,          SEN(clone),                     "clone"<br>
>>              },<br>
>> +[ 57] = { 0,   TP|SE,          SEN(fork),                      "fork"<br>
>>               },<br>
>> +[ 58] = { 0,   TP|SE,          SEN(vfork),                     "vfork"<br>
>>              },<br>
>>  [ 59] = { 3,   TF|TP|SE|SI,    SEN(execve),                    "execve"<br>
>>               },<br>
>>  [ 60] = { 1,   TP|SE,          SEN(exit),                      "exit"<br>
>>               },<br>
>>  [ 61] = { 4,   TP,             SEN(wait4),                     "wait4"<br>
>>              },<br>
>><br>
>><br>
>> However, though I put the maker on them, I cannot get expected result<br>
>> either using libunwind or libdw.<br>
>><br>
>> I read the implemention of the wrapper for clone systecall.<br>
>> It is not written in C but in x86-64 Assembly language.<br>
>> So I guess the frame structure(?) that the unwinder expects are<br>
>> not constructed when executing clone syscall. So unwinder<br>
>> cannot capture a stack trace in the context.<br>
>><br>
>> I have to take much more time for understanding the issue.<br>
>><br>
>> Masatake YAMATO<br>
>><br>
>> > Thanks,<br>
>> > Zhouyang<br>
>><br>
</blockquote></div>