I am debugging an issue with a multi-threaded TCP server application on CentOS platform. The application suddenly stopped processing connections. Even the event logging with syslog was not seen in the log files. It was as if the application become a black hole.
I killed the process with signal 11 to get the core dump. In the core dump I observed that all threads are stuck with similar patterns.
Ex:
Thread 19 (Thread 0xb2de8b70 (LWP 3722)):
#0 0x00c9e424 in __kernel_vsyscall ()
#1 0x00c17189 in __pthread_enable_asynccancel () from /lib/libpthread.so.0
#2 0x080b367d in server_debug_stats_timer_handler (tmp=0x0) at server_debug_utils.c:75 ==> this line as a event print with syslog(...)
All most all threads are attempting a syslog(...) print but gets stuck with __pthread_enable_asynccancel ().
What is being done with __pthread_enable_asynccancel () and why it isn't returning?
Here is info reg from the thread mentioned:
(gdb) info reg
eax 0xfffffe00 -512
ecx 0x80 128
edx 0x2 2
ebx 0x154ea3c4 357475268
esp 0xb2de8174 0xb2de8174
ebp 0xb2de81a8 0xb2de81a8
esi 0x0 0
edi 0x0 0
eip 0xc9e424 0xc9e424 <__kernel_vsyscall+16>
eflags 0x200246 [ PF ZF IF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
(gdb) print $orig_eax
$1 = 240
($orig_eax = 240 is SYS_futex)
One of the thread state is as shown below:
Thread 27 (Thread 0xa97d9b70 (LWP 3737)):
#0 0x00c9e424 in __kernel_vsyscall ()
#1 0x00faabb3 in inet_ntop () from /lib/libc.so.6
#2 0x00f20e76 in freopen64 () from /lib/libc.so.6
#3 0x00f96a55 in fcvt_r () from /lib/libc.so.6
#4 0x00f96fd7 in qfcvt_r () from /lib/libc.so.6
#5 0x00a19932 in app_signal_handler (signum=11) at appBaseClass.cpp:920
#6 <signal handler called>
#7 0x00f2aec5 in sYSMALLOc () from /lib/libc.so.6
#8 0x0043431a in CRYPTO_free () from /usr/local/lr/packages/stg_app/5.3.8/lib/ssl/libcrypto.so.10
#9 0x00000000 in ?? ()
(gdb) print $orig_eax $5 = 240`
Your stuck threads are in the futex() syscall, probably on an internal glibc lock taken within malloc() (the syslog() call allocates memory internally).
The reason for this deadlock isn't apparent, but I have two suggestions:
If you call syslog() (or any other non-AS-safe function, like printf()) from a signal handler anywhere in your program, that could cause a deadlock like this;
It's possible you're being bitten by a bug in futex() that was introduced in Linux 3.14 and fixed in 3.18. The bug was also backported RHEL 6.6 so would have been present for a while in CentOS too. The effect of this bug was to cause processes to fail to wake up from a FUTEX_WAIT when they should have.
Related
There is a coredump caused by my program, which shows below:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
Core was generated by `./remote_speaker plug:SLAVE='dmix:tlv320aic3106au' default rtmp://pili-publish.'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
[Current thread is 1 (Thread 0xffff802791d0 (LWP 1511))]
(gdb) bt
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x0000ffff812b9f54 in __GI_abort () at abort.c:79
#2 0x0000ffff81304d3c in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0xffff813bf638 "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x0000ffff8130c32c in malloc_printerr (str=str#entry=0xffff813bafb0 "free(): invalid pointer") at malloc.c:5332
#4 0x0000ffff8130db04 in _int_free (av=0xffff813fb9f8 <main_arena>, p=0xffff7d783ff0, have_lock=<optimized out>) at malloc.c:4173
#5 0x0000ffff81310b50 in tcache_thread_shutdown () at malloc.c:2964
#6 __malloc_arena_thread_freeres () at arena.c:949
#7 0x0000ffff81313e8c in __libc_thread_freeres () at thread-freeres.c:38
#8 0x0000ffff81614844 in start_thread (arg=0xffffc2f50ff6) at pthread_create.c:493
#9 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb)
The total threads info shows below:
(gdb) info threads
Id Target Id Frame
* 1 Thread 0xffff802791d0 (LWP 1511) __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
2 Thread 0xffff80a7a1d0 (LWP 1510) 0x0000ffff8135d084 in __GI___poll (fds=0xffff80a79740, nfds=1, timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:41
3 Thread 0xffff8127c010 (LWP 1492) 0x0000ffff81339d88 in __GI___nanosleep (requested_time=requested_time#entry=0xffffc2f510a0, remaining=remaining#entry=0x0)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
4 Thread 0xffff7e2751d0 (LWP 1515) 0x0000ffff81365bcc in __GI_epoll_pwait (epfd=6, events=0x594160 <self+128>, maxevents=32, timeout=100, set=0x0)
at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
5 Thread 0xffff8127b1d0 (LWP 1509) futex_abstimed_wait_cancelable (private=0, abstime=0x0, clockid=0, expected=0, futex_word=0x596538 <output_notice>)
at ../sysdeps/unix/sysv/linux/futex-internal.h:208
6 Thread 0xffff7fa781d0 (LWP 1512) 0x0000ffff81339d84 in __GI___nanosleep (requested_time=requested_time#entry=0xffff7fa77870, remaining=remaining#entry=0xffff7fa77870)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
thread 1-6
(gdb) thread 1
[Switching to thread 1 (Thread 0xffff802791d0 (LWP 1511))]
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 in ../sysdeps/unix/sysv/linux/raise.c
(gdb) bt
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x0000ffff812b9f54 in __GI_abort () at abort.c:79
#2 0x0000ffff81304d3c in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0xffff813bf638 "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x0000ffff8130c32c in malloc_printerr (str=str#entry=0xffff813bafb0 "free(): invalid pointer") at malloc.c:5332
#4 0x0000ffff8130db04 in _int_free (av=0xffff813fb9f8 <main_arena>, p=0xffff7d783ff0, have_lock=<optimized out>) at malloc.c:4173
#5 0x0000ffff81310b50 in tcache_thread_shutdown () at malloc.c:2964
#6 __malloc_arena_thread_freeres () at arena.c:949
#7 0x0000ffff81313e8c in __libc_thread_freeres () at thread-freeres.c:38
#8 0x0000ffff81614844 in start_thread (arg=0xffffc2f50ff6) at pthread_create.c:493
#9 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb) thread 2
[Switching to thread 2 (Thread 0xffff80a7a1d0 (LWP 1510))]
#0 0x0000ffff8135d084 in __GI___poll (fds=0xffff80a79740, nfds=1, timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:41
41 ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
(gdb) bt
#0 0x0000ffff8135d084 in __GI___poll (fds=0xffff80a79740, nfds=1, timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:41
#1 0x00000000004e8714 in nn_efd_wait ()
#2 0x00000000004e46a0 in nn_sock_recv ()
#3 0x00000000004e24b0 in nn_recvmsg ()
#4 0x00000000004e1ef4 in nn_recv ()
#5 0x0000000000445c2c in nanomsg_recv ()
#6 0x0000ffff816148f8 in start_thread (arg=0xffffc2f50ff6) at pthread_create.c:479
#7 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb) thread 3
[Switching to thread 3 (Thread 0xffff8127c010 (LWP 1492))]
#0 0x0000ffff81339d88 in __GI___nanosleep (requested_time=requested_time#entry=0xffffc2f510a0, remaining=remaining#entry=0x0) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
(gdb) bt
#0 0x0000ffff81339d88 in __GI___nanosleep (requested_time=requested_time#entry=0xffffc2f510a0, remaining=remaining#entry=0x0) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#1 0x0000ffff8135fb54 in usleep (useconds=<optimized out>) at ../sysdeps/posix/usleep.c:32
#2 0x0000000000434278 in main ()
(gdb) thread 4
[Switching to thread 4 (Thread 0xffff7e2751d0 (LWP 1515))]
#0 0x0000ffff81365bcc in __GI_epoll_pwait (epfd=6, events=0x594160 <self+128>, maxevents=32, timeout=100, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
42 ../sysdeps/unix/sysv/linux/epoll_pwait.c: No such file or directory.
(gdb) bt
#0 0x0000ffff81365bcc in __GI_epoll_pwait (epfd=6, events=0x594160 <self+128>, maxevents=32, timeout=100, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:42
#1 0x00000000004f2a14 in nn_poller_wait ()
#2 0x00000000004e712c in nn_worker_routine ()
#3 0x00000000004e9eb8 in nn_thread_main_routine ()
#4 0x0000ffff816148f8 in start_thread (arg=0xffff80a796c6) at pthread_create.c:479
#5 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb) thread 5
[Switching to thread 5 (Thread 0xffff8127b1d0 (LWP 1509))]
#0 futex_abstimed_wait_cancelable (private=0, abstime=0x0, clockid=0, expected=0, futex_word=0x596538 <output_notice>) at ../sysdeps/unix/sysv/linux/futex-internal.h:208
208 ../sysdeps/unix/sysv/linux/futex-internal.h: No such file or directory.
(gdb) bt
#0 futex_abstimed_wait_cancelable (private=0, abstime=0x0, clockid=0, expected=0, futex_word=0x596538 <output_notice>) at ../sysdeps/unix/sysv/linux/futex-internal.h:208
#1 do_futex_wait (sem=sem#entry=0x596538 <output_notice>, abstime=0x0, clockid=0) at sem_waitcommon.c:112
#2 0x0000ffff8161dd10 in __new_sem_wait_slow (sem=0x596538 <output_notice>, abstime=0x0, clockid=0) at sem_waitcommon.c:184
#3 0x0000000000529aa8 in async_output ()
#4 0x0000ffff816148f8 in start_thread (arg=0xffffc2f50fa6) at pthread_create.c:479
#5 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb) thread 6
[Switching to thread 6 (Thread 0xffff7fa781d0 (LWP 1512))]
#0 0x0000ffff81339d84 in __GI___nanosleep (requested_time=requested_time#entry=0xffff7fa77870, remaining=remaining#entry=0xffff7fa77870) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
(gdb) bt
#0 0x0000ffff81339d84 in __GI___nanosleep (requested_time=requested_time#entry=0xffff7fa77870, remaining=remaining#entry=0xffff7fa77870) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#1 0x0000ffff81339c14 in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#2 0x0000000000434ee0 in play_sound ()
#3 0x0000ffff816148f8 in start_thread (arg=0xffffc2f50ff6) at pthread_create.c:479
#4 0x0000ffff81365a7c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
I am sorry that I can not post the source code, because the code is a little much important for us.
The question is that I can not find which of my code caused this dump. There is no any my code in thread 1 after the pthread_create function. For a normal way, there must be some of my code in the threads, Is that right?
Your help would be greatly appreciated.
The question is that I can not find which of my code caused this dump
Any crash inside malloc or free is a 99.9% sign of heap corruption (freeing something twice, freeing unallocated memory, writing past the end of allocated buffer, etc.).
Here you have free() telling you that you are freeing something that was not allocated. The address being freed: 0xffff7d783ff0 looks like a stack address. It is probable that you have freed some stack address earlier.
Unfortunately, it is nearly impossible to debug heap corruption via post-mortem debugging, because the root cause of corruption may have happened 1000s of instructions earlier, possibly in completely unrelated code.
The good news: instrumenting your program with address sanitizer (gcc -fsanitize=address ...) and running such program through your tests (you do have tests, right?) usually leads you straight to the problem.
I have a program having over 300 threads to which I have attached gdb. I need to identify one particular thread whose call stack has a frame containing a variable whose value I want to use for matching. Can I script this in gdb?
(gdb) thread 3
[Switching to thread 3 (Thread 0x7f16c1eeb700 (LWP 18833))]
#4 0x00007f17f3a3bdd5 in start_thread () from /lib64/libpthread.so.0
(gdb) backtrace
#0 0x00007f17f3a3fd12 in pthread_cond_timedwait##GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007f17e72838be in __afr_shd_healer_wait (healer=healer#entry=0x7f17e05203d0) at afr-self-heald.c:101
#2 0x00007f17e728392d in afr_shd_healer_wait (healer=healer#entry=0x7f17e05203d0) at afr-self-heald.c:125
#3 0x00007f17e72848e8 in afr_shd_index_healer (data=0x7f17e05203d0) at afr-self-heald.c:572
#4 0x00007f17f3a3bdd5 in start_thread () from /lib64/libpthread.so.0
#5 0x00007f17f3302ead in clone () from /lib64/libc.so.6
(gdb) frame 3
#3 0x00007f17e72848e8 in afr_shd_index_healer (data=0x7f17e05203d0) at afr-self-heald.c:572
572 afr_shd_healer_wait (healer);
(gdb) p this->name
$6 = 0x7f17e031b910 "testvol-replicate-0"
For example, can I run a macro to loop over each thread, go to frame 3 in each of it, inspect the variable this->name and print the thead number only if the value matches testvol-replicate-0 ?
It's possible to integrate Python into GDB. Then, with the Python GDB API, you could loop over threads and search for a match. Below two examples of debugging threads with GDB and Python.
https://www.linuxjournal.com/article/11027
https://fy.blackhats.net.au/blog/html/2017/08/04/so_you_want_to_script_gdb_with_python.html
Im running into a pretty annoying problem :
I have a program which creates one thread at the start, this thread will launch other stuff during its execution (fork() immediatly followed by execve()).
Here is the bt of both threads at the point where my program reached (I think) the deadlock :
Thread 2 (LWP 8839):
#0 0x00007ffff6cdf736 in __libc_fork () at ../sysdeps/nptl/fork.c:125
#1 0x00007ffff6c8f8c0 in _IO_new_proc_open (fp=fp#entry=0x7ffff00031d0, command=command#entry=0x7ffff6c26e20 "ps -u brejon | grep \"cvc\"
#2 0x00007ffff6c8fbcc in _IO_new_popen (command=0x7ffff6c26e20 "ps -u user | grep \"cvc\" | wc -l", mode=0x42c7fd "r") at iopopen.c:296
#3-4 ...
#5 0x00007ffff74d9434 in start_thread (arg=0x7ffff6c27700) at pthread_create.c:333
#6 0x00007ffff6d0fcfd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Thread 1 (LWP 8835):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007ffff6ca0ad9 in malloc_atfork (sz=140737337120848, caller=) at arena.c:179
#2 0x00007ffff6c8d875 in __GI__IO_file_doallocate (fp=0x17a72230) at filedoalloc.c:127
#3 0x00007ffff6c9a964 in __GI__IO_doallocbuf (fp=fp#entry=0x17a72230) at genops.c:398
#4 0x00007ffff6c99de8 in _IO_new_file_overflow (f=0x17a72230, ch=-1) at fileops.c:820
#5 0x00007ffff6c98f8a in _IO_new_file_xsputn (f=0x17a72230, data=0x17a16420, n=682) at fileops.c:1331
#6 0x00007ffff6c6fcb2 in _IO_vfprintf_internal (s=0x17a72230, format=, ap=ap#entry=0x7fffffffcf18) at vfprintf.c:1632
#7 0x00007ffff6c76a97 in __fprintf (stream=, format=) at fprintf.c:32
#8-11 ...
#12 0x000000000042706e in main (argc=3, argv=0x7fffffffd698, envp=0x7fffffffd6b8) at mains/ignore/.c:146
Both stays stuck here forever with both glibc-2.17 and glibc-2.23
Any help is welcomed :'D
EDIT :
Here is a minimal example :
1 #include <stdlib.h>
2 #include <pthread.h>
3 #include <unistd.h>
4
5 void * thread_handler(void * args)
6 {
7 char * argv[] = { "/usr/bin/ls" };
8 char * newargv[] = { "/usr/bin/ls", NULL };
9 char * newenviron[] = { NULL };
10 while (1) {
11 if (vfork() == 0) {
12 execve(argv[0], newargv, newenviron);
13 }
14 }
15
16 return 0;
17 }
18
19 int main(void)
20 {
21 pthread_t thread;
22 pthread_create(&thread, NULL, thread_handler, NULL);
23
24 int * dummy_alloc;
25
26 while (1) {
27 dummy_alloc = malloc(sizeof(int));
28 free(dummy_alloc);
29 }
30
31 return 0;
32 }
Environment :
user:deadlock$ cat /etc/redhat-release
Scientific Linux release 7.3 (Nitrogen)
user:deadlock$ ldd --version
ldd (GNU libc) 2.17
EDIT 2 :
The rpm package version is : glibc-2.17-196.el7.x86_64
I can not get the line numbers using the rpm package. Here is the BT using the glibc given with the distribution : solved with debuginfo.
(gdb) thread apply all bt
Thread 2 (Thread 0x7ffff77fb700 (LWP 59753)):
#0 vfork () at ../sysdeps/unix/sysv/linux/x86_64/vfork.S:44
#1 0x000000000040074e in thread_handler (args=0x0) at deadlock.c:11
#2 0x00007ffff7bc6e25 in start_thread (arg=0x7ffff77fb700) at pthread_create.c:308
#3 0x00007ffff78f434d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
Thread 1 (Thread 0x7ffff7fba740 (LWP 59746)):
#0 0x00007ffff7878226 in _int_free (av=0x7ffff7bb8760 , p=0x602240, have_lock=0) at malloc.c:3927
#1 0x00000000004007aa in main () at deadlock.c:28
This is a custom-compiled glibc. It is possible that something went wrong with the installation. Note that Red Hat Enterprise Linux 7.4 backports a fix for a deadlock between malloc and fork, and you are missing that because you compiled your own glibc. The fix for the upstream bug went only into upstream version 2.24, so if you are basing your custom build on that, you may not have this fix. (Although the backtrace would look differently for that one.)
I think we fixed at least another post-2.17 libio-related deadlock bug.
EDIT I have been dealing with fork-related deadlocks for too long. There are multiple issues with the reproducer as posted:
There is no waitpid call for the PID. As a result, the process table will be quickly filled with zombies.
No error checking for execve. If the /usr/bin/ls pathname does not exist (for example, on a system which did not undergo UsrMove), execve will return, and the next iteration of the loop will launch another vfork call.
I fixed both issues (because debugging what is approaching a fork bomb is not fun at all), but I can't reproduce a hang with glibc-2.17-196.el7.x86_64.
We have created a multithreaded, single core application running on Ubuntu.
When we call getaddrinfo and gethostbyname from the main process, it does not crash.
However when we create a thread from the main process and the functions getaddrinfo and gethostbyname are called from the created thread, it always crashes.
Kindly help.
Please find the call stack below:
#0 0xf7e9f890 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1 0xf7e9fa73 in __res_ninit () from /lib/i386-linux-gnu/libc.so.6
#2 0xf7ea0a68 in __res_maybe_init () from /lib/i386-linux-gnu/libc.so.6
#3 0xf7e663be in ?? () from /lib/i386-linux-gnu/libc.so.6
#4 0xf7e696bb in getaddrinfo () from /lib/i386-linux-gnu/libc.so.6
#5 0x080c4e35 in mn_task_entry (args=0xa6c4130 <ipc_os_input_params>) at /home/nextg/Alps_RT/mn/src/mn_main.c:699
#6 0xf7fa5d78 in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#7 0xf7e9001e in clone () from /lib/i386-linux-gnu/libc.so.6
The reason the getaddrinfo was crashing because, the child thread making the call did not have sufficient stack space.
Using ACE C++ version 6.5.1 libraries classes which use ACE_Thread::spawn_n with default ACE_DEFAULT_THREAD_PRIORITY (1024*1024) will crash when calling gethostbyname/getaddrinfo inside child as reported by Syed Aslam. libxml2 schema parsing takes forever, using a child thread Segment Faulted after calling xmlNanoHTTPConnectHost as it tries to resolve schemaLocation.
ACE_Task activate
const ACE_TCHAR *thr_name[1];
thr_name[0] = "Flerf";
// libxml2-2.9.7/nanohttp.c:1133
// gethostbyname will crash when child thread making the call
// has insufficient stack space.
size_t stack_sizes[1] = {
ACE_DEFAULT_THREAD_STACKSIZE * 100
};
const INT ret = this->activate (
THR_NEW_LWP/*Light Weight Process*/ | THR_JOINABLE,
1,
0/*force_active*/,
ACE_DEFAULT_THREAD_PRIORITY,
-1/*grp_id*/,
NULL/*task*/,
NULL/*thread_handles[]*/,
NULL/*stack[]*/,
stack_sizes/*stack_size[]*/,
NULL/*thread_ids[]*/,
thr_name
);
I am interested in running a multithreaded application in the supervision of another monitoring process. The monitoring process should be able to get and set CPU registers of all the threads in the monitored application. I know how to do this for a single threaded application. But I'm interested in knowing how to extend this for multithreaded applications.
You can use thread id instead of pid in ptrace and it should work fine. However thread management needs to be done by you.
Use thread id instead of pid in ptrace, is not a solution.
Because in Linux-64, pthread_t--unsigned long, pid_t--unsigned int.
I wondered this issue, too.
I have another method to get thread-reg-info, using gdb.
This is my code:
void *ThrFunc(void *para)
{
printf("hello world.\n");
sleep(-1); // suspend the thread.
}
int main()
{
pthread_t ptid;
int ret = pthread_create(&ptid, NULL, ThrFunc, NULL);
if(ret != 0)
{
exit(errno);
}
pthread_join(ptid, NULL);// suspend the main thread.
return 0;
}
The following is gdb debug details:
(gdb) info thread
2 Thread 0x7ffff7fe9700 (LWP 4533) 0x00000033d98ab91d in nanosleep () from /lib64/libc.so.6
* 1 Thread 0x7ffff7feb720 (LWP 4530) 0x00000033d9c080ad in pthread_join () from /lib64/libpthread.so.0
(gdb) info reg
rax 0xfffffffffffffe00 -512
...
rip 0x33d9c080ad 0x33d9c080ad <pthread_join+269>
eflags 0x246 [ PF ZF IF ]
...
(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff7fe9700 (LWP 4533))]#0 0x00000033d98ab91d in nanosleep () from /lib64/libc.so.6
(gdb) info thread
* 2 Thread 0x7ffff7fe9700 (LWP 4533) 0x00000033d98ab91d in nanosleep () from /lib64/libc.so.6
1 Thread 0x7ffff7feb720 (LWP 4530) 0x00000033d9c080ad in pthread_join () from /lib64/libpthread.so.0
(gdb) info reg
rax 0xfffffffffffffdfc -516
...
rip 0x33d98ab91d 0x33d98ab91d <nanosleep+45>
eflags 0x293 [ CF AF SF IF ]
...
I hope this will help you.
By the way, I also want to know: How to use ptrace() to get a thread registers details?