In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly shows you "how to generate deadlocks in the Linux platform", the content is easy to understand, clear, hope to help you solve your doubts, the following let the editor lead you to study and learn "how to generate deadlocks in the Linux platform" this article.
Deadlock (deallocks): refers to two or more processes (threads) in the execution process, due to competition for resources caused by a phenomenon of waiting for each other, if there is no external force, they will not be able to advance. At this point, it is said that the system is in a deadlock state or the system has a deadlock, and these processes (threads) that are always waiting for each other are called deadlock processes (threads). Because the occupation of resources is mutually exclusive, when a process applies for resources, the relevant process (thread) can never allocate the necessary resources and can not continue to run without external assistance, which leads to a special phenomenon deadlock.
A cross-holding deadlock situation in which two or more threads in the executing program are permanently blocked (waiting), and each thread is waiting for resources that are occupied and blocked by other threads. For example, if thread 1 locks record An and waits for record B, while thread 2 locks record B and waits for record A, the two threads have a deadlock. In computer systems, if the resource allocation strategy of the system is improper, it may be more common that there are errors in the programs written by programmers, which will lead to the deadlock of the process due to improper competition for resources.
Four necessary conditions for deadlock generation
(1) Mutual exclusion condition: a resource can only be used by one process (thread) at a time.
(2) request and retention conditions: when a process (thread) is blocked by a request for resources, it holds on to the resources it has acquired.
(3) No deprivation condition: the resources that have been obtained by this process (thread) cannot be forcibly deprived until they are used up.
(4) Loop waiting condition: a loop waiting resource relationship is formed between multiple processes (threads).
Figure 1. Schematic diagram of a deadlock with a cross lock:
Note: after executing func2 and func4, child thread 1 acquires lock An and is trying to acquire lock B, but child thread 2 acquires lock B and is trying to acquire lock A, so child thread 1 and child thread 2 will have no way to get lock An and lock B, because they are occupied by each other and will never be released, so deadlock occurs.
Use pstack and gdb tools to analyze deadlock programs
A brief introduction of pstack on Linux platform
Pstack is a very useful tool under Linux (such as Red Hat Linux system, Ubuntu Linux system, etc.). Its function is to print out the stack information of this process. You can output the call relationship stack for all threads.
A brief introduction of gdb on Linux platform
GDB is a powerful program debugging tool under UNIX released by GNU open source organization. The Linux system contains the GNU debugger gdb, which is a debugger used to debug C and C++ programs. It enables program developers to observe the internal structure of the program and the use of memory while the program is running.
Some of the main features provided by gdb are as follows:
1 run the program and set the parameters and environment that can affect the operation of the program
2 the control program stops running under the specified conditions
3 when the program stops, you can check the status of the program
4 when the program crash, you can check the core file
5 you can correct the errors of the program and rerun the program
6 you can dynamically monitor the value of variables in the program
7 you can step through the code to observe the running status of the program.
The object of gdb program debugging is an executable file or process, not the source code file of the program. However, not all executables can be debugged with gdb. If you want to make the resulting executable available for debugging, you need to specify that the program contains debugging information at compile time by adding the-g parameter to the compiler when executing the Graph + (gcc) instruction. The debugging information contains the type of each variable in the program and the address mapping in the executable file, as well as the line number of the source code. Gdb uses this information to associate source code with machine code. There are many basic commands of gdb, which are not described in detail. If you need to know more, please refer to the gdb manual.
Listing 1. Test program
# include # include # include pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex4 = PTHREAD_MUTEX_INITIALIZER; static int sequence1 = 0; static int sequence2 = 0; int func1 () {pthread_mutex_lock (& mutex1); + + sequence1; sleep (1); pthread_mutex_lock (& mutex2); + + sequence2 Pthread_mutex_unlock (& mutex2); pthread_mutex_unlock (& mutex1); return sequence1;} int func2 () {pthread_mutex_lock (& mutex2); + + sequence2; sleep (1); pthread_mutex_lock (& mutex1); + + sequence1; pthread_mutex_unlock (& mutex1); pthread_mutex_unlock (& mutex2); return sequence2 } void* thread1 (void* arg) {while (1) {int iRetValue = func1 (); if (iRetValue = = 100000) {pthread_exit (NULL);} void* thread2 (void* arg) {while (1) {int iRetValue = func2 () If (iRetValue = = 100000) {pthread_exit (NULL);} void* thread3 (void* arg) {while (1) {sleep (1); char szBuf [128,128]; memset (szBuf, 0, sizeof (szBuf)); strcpy (szBuf, "thread3") } void* thread4 (void* arg) {while (1) {sleep (1); char szBuf [128]; memset (szBuf, 0, sizeof (szBuf)); strcpy (szBuf, "thread3");} int main () {pthread_t tid [4] If (pthread_create (& tid [0], NULL, & thread1, NULL)! = 0) {_ exit (1);} if (pthread_create (& tid [1], NULL, & thread2, NULL)! = 0) {_ exit (1) } if (& tid [2], NULL, & thread3, NULL)! = 0) {_ exit (1);} if (pthread_create (& tid [3], NULL, & thread4, NULL)! = 0) {_ exit (1);} sleep (5); / / pthread_cancel (tid [0]); pthread_join (tid [0], NULL) Pthread_join (tid [1], NULL); pthread_join (tid [2], NULL); pthread_join (tid [3], NULL); pthread_mutex_destroy (& mutex1); pthread_mutex_destroy (& mutex2); pthread_mutex_destroy (& mutex3); pthread_mutex_destroy (& mutex4); return 0;}
Listing 2. Compile test program
[dyu@xilinuxbldsrv purify] $lock.cpp +-g lock-o lock-lpthread
Listing 3. Find the process number of the test program
[dyu@xilinuxbldsrv purify] $ps-ef | grep lock dyu 6721 5751 0 15:21 pts/3 00:00:00. / lock
Listing 4. Output of pstack (pstack-process number) executed for the first time on a deadlock process
[dyu@xilinuxbldsrv purify] $pstack 6721 Thread 5 (Thread 0x41e37940 (LWP 6722)): # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 # 1 0x0000003d1a808e1a in _ L_lock_1034 () from / lib64/libpthread.so.0 # 2 0x0000003d1a808cdc in pthread_mutex_lock () from / lib64/libpthread.so.0 # 3 0x0000000000400a9b in func1 () () # 4 0x0000000000400ad7 in thread1 (void*) () # 5 0x0000003d1a80673d in start_thread () From / lib64/libpthread.so.0 # 6 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 4 (Thread 0x42838940 (LWP 6723)): # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 # 1 0x0000003d1a808e1a in _ L_lock_1034 () from / lib64/libpthread.so.0 # 2 0x0000003d1a808cdc in pthread_mutex_lock () from / lib64/libpthread.so.0 # 3 0x0000000000400a17 in func2 () () # 4 0x0000000000400a53 in thread2 (void*) () # 5 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 6 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 3 (Thread 0x43239940 (LWP 6724)): # 0 0x0000003d19c9a541 in nanosleep () from / lib64/libc.so.6 # 1 0x0000003d19c9a364 in sleep () from / lib64/libc.so.6 # 2 0x00000000004009bc in thread3 (void*) () # 3 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 4 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 2 (Thread 0x43c3a940 (LWP 6725)): # 0 0x0000003d19c9a541 in nanosleep () from / lib64/libc.so.6 # 1 0x0000003d19c9a364 in sleep () from / lib64/libc.so.6 # 2 0x0000000000400976 in thread4 (void*) () # 3 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 4 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 1 (Thread 0x2b984ecabd90 (LWP 6721) ): # 0 0x0000003d1a807b35 in pthread_join () from / lib64/libpthread.so.0 # 1 0x0000000000400900 in main ()
Listing 5. The output of the second execution of pstack (pstack-process number) on the deadlock process
[dyu@xilinuxbldsrv purify] $pstack 6721 Thread 5 (Thread 0x40bd6940 (LWP 6722)): # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 # 1 0x0000003d1a808e1a in _ L_lock_1034 () from / lib64/libpthread.so.0 # 2 0x0000003d1a808cdc in pthread_mutex_lock () from / lib64/libpthread.so.0 # 3 0x0000000000400a87 in func1 () () # 4 0x0000000000400ac3 in thread1 (void*) () # 5 0x0000003d1a80673d in start_thread () From / lib64/libpthread.so.0 # 6 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 4 (Thread 0x415d7940 (LWP 6723)): # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 # 1 0x0000003d1a808e1a in _ L_lock_1034 () from / lib64/libpthread.so.0 # 2 0x0000003d1a808cdc in pthread_mutex_lock () from / lib64/libpthread.so.0 # 3 0x0000000000400a03 in func2 () () # 4 0x0000000000400a3f in thread2 (void*) () # 5 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 6 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 3 (Thread 0x41fd8940 (LWP 6724)): # 0 0x0000003d19c7aec2 in memset () from / lib64/libc.so.6 # 1 0x00000000004009be in thread3 (void*) () # 2 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 3 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 2 (Thread 0x429d9940 (LWP 6725)): # 0 0x0000003d19c7ae0d in memset () from / lib64/libc.so.6 # 1 0x0000000000400982 in thread4 (void*) () # 2 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 3 0x0000003d19cd40cd in clone () from / lib64/libc.so.6 Thread 1 (Thread 0x2af906fd9d90 (LWP 6721)): # 0 0x0000003d1a807b35 in pthread_join () from / lib64/libpthread.so.0 # 1 0x0000000000400900 in main ()
Check the function call relationship stack of this process for analysis: when the process hangs, use pstack to check the function call stack of the process many times, the deadlock thread will always be in the state of waiting for lock, compare the output results of the function call stack many times to determine which two threads (or several threads) have been unchanged and have been in the state of waiting for lock (there may be two threads that have not changed all the time).
Output analysis:
According to the output comparison above, it can be found that thread 1 and thread 2 change from the sleep function of the first pstack output to the memset function of the second pstack output. However, thread 4 and thread 5 have been in an equal lock state (pthread_mutex_lock), and there is no change in two consecutive pstack information output, so we can speculate that thread 4 and thread 5 have a deadlock.
Gdb into thread output:
Listing 6. Then go to the deadlock process via gdb attach
(gdb) info thread 5 Thread 0x41e37940 (LWP 6722) 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 4 Thread 0x42838940 (LWP 6723) 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 3 Thread 0x43239940 (LWP 6724) 0x0000003d19c9a541 in nanosleep () from / lib64/libc.so.6 2 Thread 0x43c3a940 (LWP 6725) 0x0000003d19c9a541 in nanosleep () from / lib64/libc.so.6 * 1 Thread 0x2b984ecabd90 (LWP 6721) 0x0000003d1a807b35 in pthread_join () from / lib64/libpthread.so.0
Listing 7. Switch to the output of thread 5
(gdb) thread 5 [Switching to thread 5 (Thread 0x41e37940 (LWP 6722))] # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 (gdb) where # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 # 1 0x0000003d1a808e1a in _ L_lock_1034 () from / lib64/libpthread.so.0 # 2 0x0000003d1a808cdc in pthread_mutex_lock () from / lib64/libpthread.so.0 # 3 0x0000000000400a9b in func1 () at lock.cpp:18 # 4 0x0000000000400ad7 in thread1 (arg=0x0) at lock.cpp:43 # 5 0x0000003d1a80673d in start_thread () from / lib64/libpthread.so.0 # 6 0x0000003d19cd40cd in clone () from / lib64/libc.so.6
Listing 8. Output of thread 4 and thread 5
(gdb) f 3 # 3 0x0000000000400a9b in func1 () at lock.cpp:18 18 pthread_mutex_lock (& mutex2); (gdb) thread 4 [Switching to thread 4 (Thread 0x42838940 (LWP 6723))] # 0 0x0000003d1a80d4c4 in _ lll_lock_wait () from / lib64/libpthread.so.0 (gdb) f 3 # 3 0x0000000000400a17 in func2 () at lock.cpp:31 31 pthread_mutex_lock (& mutex1) (gdb) p mutex1 $1 = {_ _ data = {_ _ lock = 2, _ _ count = 0, _ _ owner = 6722, _ _ nusers = 1, _ _ kind = 0, _ _ spins = 0, _ _ list = {_ _ prev = 0x0, _ _ next = 0x0}}, _ _ size = "\ 002\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000\ 000",'\ 000' _ _ align = 2} (gdb) p mutex3 $2 = {_ _ data = {_ _ lock = 0, _ _ count = 0, _ _ owner = 0, _ _ nusers = 0, _ _ kind = 0, _ _ spins = 0, _ _ list = {_ _ prev = 0x0, _ _ next = 0x0}}, _ _ size ='\ 000', _ _ align = 0} (gdb) p mutex2 $3 = {_ data = {_ lock = 2, _ _ count = 0 _ _ owner = 6723, _ _ nusers = 1, _ _ kind = 0, _ _ spins = 0, _ _ list = {_ _ prev = 0x0, _ _ next = 0x0}}, _ _ size = "\ 002\ 000\ 000\ 000\ 000\ 000\ 000C\ 032\ 000\ 000\ 001",'\ 000', _ align = 2} (gdb)
From above, we can see that thread 4 is trying to acquire a lock mutex1, but the lock mutex1 has been obtained by a thread with a LWP of 6722 (_ _ owner = 6722), and thread 5 is trying to acquire a lock mutex2, but the lock mutex2 has been obtained by a thread with a LWP of 6723 (_ _ owner = 6723). From the output of pstack, we can find that LWP 6722 corresponds to thread 5 and LWP 6723 corresponds to thread 4. So we can conclude that thread 4 and thread 5 have a deadlock that crosses locks. Looking at the source code of the thread, it is found that thread 4 and thread 5 use both mutex1 and mutex2, and the application order is not reasonable.
The above is all the contents of the article "how to generate deadlocks on the Linux platform". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.