Locate the deadlock caused by the critical section

Source: Internet
Author: User

Locate the deadlock caused by the critical section

-------- Easy debugging network original welcome reprint, reprint please indicate the source of www.debug-easy.com --------
Code in this article (45kb)

In the development of multi-threaded programs, criticalsection is usually used as the synchronization mechanism because of the efficiency. Beginners often encounter deadlocks when designing and developing multi-threaded programs. Yesterday I saw a buddy posting to ask this question (obviously depressed ). Here is an example to illustrate how to easily locate this deadlock problem without intel's thread checker, thread profiler, and powerful windbg. It just uses the local vc6 built-in debugger.

First paste the code of the deadlock example:

·/************************************** *****************/

·/* Procedure: deadlock */

·/* Function: deadlock caused by a criticalsection object in a multi-threaded environment */

·/* Author: Easy debugging network www.debug-easy.com */

·/* Date */

·/************************************** *****************/

· # Include <windows. h>

· # Include <stdio. h>

· Critical_section g_cs1;

· Critical_section g_cs2;

· DWORD winapi worker (lpvoid lpparam)

·{

· If (INT) lpparam = 7)

·{

· While (1)

·{

· Printf ("Worker [% x]: keep me alive \ n", getcurrentthreadid ());

· Sleep (1000 );

·}

·}

· Else

·{

· Printf ("Worker [% x]: Prepare to enter the critical segment g_cs2 \ n", getcurrentthreadid ());

· Entercriticalsection (& g_cs2 );

· Printf ("Worker [% x]: The Critical segment g_cs2 \ n", getcurrentthreadid () is successfully entered ());

·

· Printf ("Worker [% x]: Prepare to enter the critical segment g_cs1 \ n", getcurrentthreadid ());

· Entercriticalsection (& g_cs1 );

· Printf ("Worker [% x]: The Critical segment g_cs1 \ n", getcurrentthreadid () is successfully entered ());

·}

· Return 0;

·}

· Int main (INT argc, char * argv [])

·{

· Initializecriticalsection (& g_cs1 );

· Initializecriticalsection (& g_cs2 );

· Printf ("Main [% x]: Prepare to enter the critical segment g_cs1 \ n", getcurrentthreadid ());

· Entercriticalsection (& g_cs1 );

· Printf ("Main [% x]: The Critical segment g_cs1 \ n", getcurrentthreadid () is successfully entered ());

· Handle hthread [8];

· For (INT I = 0; I <8; I ++)

·{

· Hthread [I] = createthread (null, 0, worker, (lpvoid) I, 0, null );

·}

· Printf ("Main [% x]: Prepare to enter the critical segment g_cs2 \ n", getcurrentthreadid ());

· Entercriticalsection (& g_cs2 );

· Printf ("Main [% x]: The Critical segment g_cs2 is successfully entered! \ N ", getcurrentthreadid ());

· Return 0;

·}

Compile the above program first. Select coding generation from project --> setting --> C ++ --> catalog and select debug multithreaded from user run-time library. Press F7 to build, and then F5 directly debug and run. The following output is displayed:

Here, the worker is the 16 threads created in main, and the [] contains the thread ID. Now the program has been deadlocked and has not exited. Only one thread is output every second. What we need is this effect. Now we will go to our topic. Locate the cause of the deadlock (of course, the example here is very simple to see, but the actual situation is often much more complex, and the analysis and positioning method is unchanged ).

Step 1: Pause the running of the program. You can use the small button in the debug toolbar to indicate the pause (even if you use vc6 for the first time, you only need to know the button when you have used Walkman, recorder, MP3, VCD, and DVD, do not know pp ). I don't know how to find the debug toolbar. Let's take a look at the VC programmer's guide. Or debug --> break in the menu.

Step 2: After the pause, we usually see the full screen assembly code. Do not panic. Open the call Stack window (press the shortcut key Alt + 7, or use the menu View> debug window --> call stack to activate it) and you will probably see the following content:

Here we can see the call stack of the current thread. Without an accident, this thread should be the thread that is still output continuously (review the thread scheduling content in the operating system without thinking clearly, and Windows internals is recommended ). In fact, from the worker (void * 00000007...) Row selected above ...) The thread at I = 7. Double-click this line to see it, for example:

The contents of these circles. The first is lpparam. We can see that the value is 7, which is exactly the 8th thread we created. It is output continuously here. The content in the second circle is g_cs2, and the third is g_cs1.

Step 3: Check the two global variables criticalsection to see what the current situation is. Quickwatch variables.

The time is relatively tight. Let's talk about the owningthread field that is most concerned about. We can see that the owningthread of g_cs1 is 0x3f18, And the owningthread of g_cs2 is 0x36b4. This indicates that criticalsection g_cs1 is occupied by thread 0x3f18, while g_cs2 is occupied by thread 0x36b4.

Step 4: check what the threads occupy the two critical zones are doing. Select the menu debug --> thread and see the following output:

We can see a line in the front blue background with a '*' sign at the beginning, which indicates the current thread of the debugger. The preceding 7640 is the thread ID, and the following [Worker] is the current running position. We are concerned about the 0x3f18 and 0x36b4 threads. We can see them in the previous step. 0x3f18 is the main thread, and 0x36b4 is a worker thread. Let's take a look at the main thread and double-click the line 0x3f18. It is probably a full screen compilation.

Step 5: perform the same operations as step 2 and find the location of our code from the call stack. Then we found the code on the following line:

Entercriticalsection (& g_cs2 );

What is it about? The main thread is waiting to enter the critical section g_cs2. As mentioned earlier, the main thread has already entered g_cs1, while g_cs2 is occupied by thread 0x36b4. Therefore, if g_cs2 is not released, main will remain occupied by g_cs1, and g_cs2. Repeat Step 4 to see what 0x36b4 is doing. We can see that it also stops on a line similar to code:

Entercriticalsection (& g_cs1 );

Well, obviously. This thread has already entered g_cs2, but g_cs1; g_cs1 has been occupied by main, and main has to enter g_cs2, which forms a deadlock condition: they own each other and wait cyclically.

Step 6: solve the problem. I figured out the cause of the deadlock, and the rest is the condition for damage to the deadlock. It depends on the service to solve it.

How about the vc6 debugger. Of course, although this article uses vc6 as the environment, other development environments should have similar functions. The basic idea is to confirm the deadlocked thread or variable. The example here shows the threads without deadlocks. We can see the values of g_cs1 and 2, so we can check which two threads have problems. The actual situation is usually to roughly confirm the deadlock thread according to the business, and then to see which threads occupy which criticalsection objects are waiting cyclically, and finally to clarify the relationship, remove coupling to solve deadlocks.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.