Critical thread gets interuped and enters in a deadlock

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
expert_vision
Posts: 21
Joined: 13 Jan 2014, 10:47

Critical thread gets interuped and enters in a deadlock

04 Feb 2015, 14:25

The script below may enter in a deadlock if you left click madly on the on the list view as soon as it starts.
This is what happens:
  • ListGui is created and shown
  • UpdateList label is set to be triggered 1 sec later
  • lots of calls to ListEvent are triggered as I click very fast the list view
  • after a second UpdateList is called which enters in a critical state
  • it manages to add a part of the list view items and it freezes; enters in a deadlock and the gui is unresponsive until window is unfocussed
Why is the event interrupting the critical thread? And most important, why does the gui thread enter in a dead lock (along with the timer thread UpdateList )?

Code: Select all

Gui, ListGui:Add, ListView, w300 h200 gListEvent vListControl AltSubmit, Col1|Col2|Col3
Gui, ListGui:Add, Edit, vEventEdit
Gui, ListGui:Show
SetTimer, UpdateList, 1000
return

ListEvent:
Loop, 1000
	GuiControl, ListGui:, EventEdit, % A_GuiEvent . A_Index
return


UpdateList:
SetTimer, UpdateList, Off
SetBatchLines, -1 ;doesn't work
Sleep, 10
Critical
Gui, ListGui:Default
Gui, ListView, ListControl
Loop, 200
	LV_Add("", "Many", "many", "items")
Loop, 3
	LV_ModifyCol(A_Index, "AutoHdr")
Critical, Off
return

ListGuiGuiClose:
ExitApp
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

04 Feb 2015, 17:07

ListViews are prone to this sort of problem. I'm not sure whether it's an issue with the design of AutoHotkey or ListViews, or just because of the excessive number of notifications ListViews send. Maybe all of the above.

Note: The timer thread also interrupts the event thread.
Sleep, 10
Why? The thread may be interrupted at this point, before you make it "critical". Critical should nearly always be used as the first line of the sub, and you should not Sleep or 'Wait.

Don't turn off Critical unless you want the thread to be interrupted. It is a thread-specific setting, so you do not need to turn it off prior to returning.

If the problem still isn't solved: Why are you allowing interaction with the control while you are updating/populating it? If you're expecting the update to take a while, you should probably disable the control.

SetBatchLines -1 will do nothing because
Critical wrote:In v1.0.47+, turning on Critical also puts SetBatchLines -1 into effect for the current thread.
I tried to debug using ListVars, but my attempts to access ListVars appeared to release the program from deadlock.

I could not produce any problems on my i7 system until I ran the script in a VM with capped CPU usage (10% or 20%).
expert_vision
Posts: 21
Joined: 13 Jan 2014, 10:47

Re: Critical thread gets interuped and enters in a deadlock

05 Feb 2015, 10:39

The reason I use Critical when I populate/update the ListView is to make sure the list view functions operates on the right one, because there are multiple ListViews that are concurrently being updated. Disabling the ListView during population/update would fix the deadlock but produces an annoying flicker and makes scrolling or selection impossible, because my ListViews are updated every second.
Why? The thread may be interrupted at this point, before you make it "critical". Critical should nearly always be used as the first line of the sub, and you should not Sleep or 'Wait.
The reason I added the Sleep is because I suspected that Critical is not atomic and doesn't come into effect instantly, so I've set manually SetBatchLines, -1, sleep to make sure it comes into effect and then call Critical. Anyway, it is not the case, as the event interrupts the timer way later and not at the execution of Critical

After further testing I just realized that this is not an atomicity problem, but simply the ListView event doesn't wait for the critical thread.
If the ListView update is long enough, and a ListView event is triggered at that time, it interrupts the critical thread, executes and returns, living the critical thread in a lingering state until window is unfocused. When window is unfocused the critical thread resumes. So to reproduce this, the ListView notification spam is not required, a single one can do it.

Code: Select all

Gui, ListGui:Add, ListView, w300 h200 gListEvent vListControl AltSubmit, Col1|Col2|Col3
Gui, ListGui:Add, Edit, vEventEdit
Gui, ListGui:Show
Critical
Gui, ListGui:Default
Gui, ListView, ListControl
Loop, 100000
	LV_Add("", "Many", "many", "items")
Loop, 3
	LV_ModifyCol(A_Index, "AutoHdr")
return

ListEvent:
GuiControl, ListGui:, EventEdit, % A_GuiEvent
return

ListGuiGuiClose:
ExitApp
If the system is too fast increase the number of LV_Add calls.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

05 Feb 2015, 17:18

expert_vision wrote:The reason I added the Sleep is because I suspected that Critical is not atomic and doesn't come into effect instantly,
If you put Critical as the first line of the sub, the thread will start off Critical before any commands execute. Even if it's not the first line, calling Critical puts the settings into effect immediately. There is absolutely no need to Sleep to put the threads's own settings into effect.
Anyway, it is not the case, as the event interrupts the timer way later and not at the execution of Critical
What makes you think that? I'm fairly certain that the event thread only interrupts the timer before it is Critical. The deadlock occurs for some other reason.
If the ListView update is long enough, and a ListView event is triggered at that time, it interrupts the critical thread, executes and returns,
I was able to quite reliably reproduce the problem with your new script; thanks. However, the ListView thread does not interrupt the critical thread - internal handling of the WM_NOTIFY message occurs while the Critical thread is running, but this does not cause any new threads to execute until after the Critical thread returns.

I think that Critical 10000 (where 10000 >= the time needed to update the control) would avoid the problem, but it also makes the script/control unresponsive until the update finishes.
expert_vision
Posts: 21
Joined: 13 Jan 2014, 10:47

Re: Critical thread gets interuped and enters in a deadlock

05 Feb 2015, 18:21

What makes you think that? I'm fairly certain that the event thread only interrupts the timer before it is Critical.
On my system the ListView population in that script takes quiet a while, so if I click on the ListView a couple of seconds after the script started, I'm way after the thread has been declared Critical, and yet the ListView event thread executes and fills the Edit control with A_GuiEvent, interrupting the Critical thread, which for some reason doesn't resume after event thread finishes and waits indefinitely.

One suspicious fact is that after the critical thread gets interrupted and enters in a deadlock, the AHK interpreter CPU usage is as high as it was before it was interrupted. So the thread it's not really in a locked/waiting state, it's doing something in an infinite loop. Maybe LV_Add can't access the ListView? And whatever it prevents it form accessing it, it's resolved when the window is deactivated?
I think that Critical 10000 (where 10000 >= the time needed to update the control) would avoid the problem, but it also makes the script/control unresponsive until the update finishes.
I thing I'm going to implement my own semaphores/locking system instead of Critical with a simple variable as a flag, which will keep both thread safety and script responsiveness ok.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

05 Feb 2015, 20:13

expert_vision wrote:On my system the ListView population in that script takes quiet a while, [...] the ListView event thread executes and fills the Edit control with A_GuiEvent, interrupting the Critical thread,
On my system, the ListView population (in your latest script) takes quite a while, and the ListView event thread does not execute. The Edit control remains blank. The program deadlocks anyway.
Maybe LV_Add can't access the ListView?
It's not LV_Add. It deadlocks between calls to LV_Add, not while LV_Add is running. This occurs after AutoHotkey returns from processing the WM_NOTIFY messages which were sent by the ListView in response to your mouse clicks. AutoHotkey processes them by posting another message to the message queue, which is not processed until the critical thread completes (or at least, that's how it's designed to work, and how it happens on my system). This latter message causes the ListView event sub to execute.

So I think the deadlock is either in AutoHotkey's message loop, or outside AutoHotkey's control, in the ListView control's handling of messages/notifications.
And whatever it prevents it form accessing it, it's resolved when the window is deactivated?
When the window is deactivated, several messages are sent to the window, including ListView notification messages. It could be this rather than the actual deactivation. Deactivating the window might also release mouse capture, if the control has captured the mouse.
I thing I'm going to implement my own semaphores/locking system instead of Critical with a simple variable as a flag, which will keep both thread safety and script responsiveness ok.
You could try simply disabling (some) ListView notifications while updating: GuiControl -g or -AltSubmit.
expert_vision
Posts: 21
Joined: 13 Jan 2014, 10:47

Re: Critical thread gets interuped and enters in a deadlock

06 Feb 2015, 12:20

On my system, the ListView population (in your latest script) takes quite a while, and the ListView event thread does not execute.
Yep, I messed up. You are right the Edit control remains blank.
So I think the deadlock is either in AutoHotkey's message loop, or outside AutoHotkey's control, in the ListView control's handling of messages/notifications.
I looked with Spy++ at the message stream processed by the main window and noticed an infinite loop of messages (0x0414) being posted during the deadlock, right after WM_LBUTTONDOWN is being forwarded by the ListView.

Code: Select all

<000893> 001403E0 R WM_NOTIFY
<000894> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CDDA0
<000895> 001403E0 R WM_NOTIFY
<000896> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CDDA0
<000897> 001403E0 R WM_NOTIFY
<000898> 001403E0 S WM_PARENTNOTIFY fwEvent:WM_LBUTTONDOWN xPos:150 yPos:122
<000899> 001403E0 R WM_PARENTNOTIFY
<000900> 001403E0 S WM_MOUSEACTIVATE hwndTopLevel:001403E0 nHittest:HTCLIENT uMsg:WM_LBUTTONDOWN
<000901> 001403E0 R WM_MOUSEACTIVATE fuActivate:MA_ACTIVATE
<000902> 001403E0 S WM_WINDOWPOSCHANGING lpwp:008CDFB8
<000903> 001403E0 R WM_WINDOWPOSCHANGING
<000904> 001403E0 S WM_WINDOWPOSCHANGED lpwp:008CDFB8
<000905> 001403E0 R WM_WINDOWPOSCHANGED
<000906> 001403E0 S WM_NCACTIVATE fActive:True
<000907> 001403E0 R WM_NCACTIVATE
<000908> 001403E0 S WM_ACTIVATE fActive:WA_CLICKACTIVE fMinimized:False hwndPrevious:002003DE
<000909> 001403E0 S message:0x0400 [User-defined:WM_USER+0] wParam:00000000 lParam:00000000
<000910> 001403E0 R message:0x0400 [User-defined:WM_USER+0] lResult:00000000
<000911> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CC4FC
<000912> 001403E0 R WM_NOTIFY
<000913> 001403E0 R WM_ACTIVATE
<000914> 001403E0 S WM_SETCURSOR hwnd:0011034E nHittest:HTCLIENT wMouseMsg:WM_LBUTTONDOWN
<000915> 001403E0 R WM_SETCURSOR fHaltProcessing:False
<000916> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CDC5C
<000917> 001403E0 R WM_NOTIFY
<000918> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CDAE8
<000919> 001403E0 R WM_NOTIFY
<000920> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CDAE8
<000921> 001403E0 R WM_NOTIFY
<000922> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000046 lParam:00000000
<000923> 001403E0 S WM_NOTIFY idCtrl:3 pnmh:008CAD80
<000924> 001403E0 R WM_NOTIFY
<000925> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000043 lParam:00000000
<000926> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000549 lParam:00000006
<000927> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000046 lParam:00000000
<000928> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000043 lParam:00000000
<000929> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000549 lParam:00000006
<000930> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000046 lParam:00000000
<000931> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000043 lParam:00000000
<000932> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000549 lParam:00000006
<000933> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000046 lParam:00000000
<000934> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000043 lParam:00000000
<000935> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000549 lParam:00000006
<000936> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000046 lParam:00000000
<000937> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000043 lParam:00000000
<000938> 001403E0 P message:0x0414 [User-defined:WM_USER+20] wParam:00000549 lParam:00000006
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

06 Feb 2015, 18:27

I did some debugging last night and think I got to the bottom of this.
The docs wrote:Unlike high-priority threads, events that occur during a critical thread are not discarded. For example, if the user presses a hotkey while the current thread is critical, the hotkey is buffered indefinitely until the current thread finishes or becomes noncritical, at which time the hotkey is launched as a new thread.
This is implemented by AutoHotkey's message loop being picky about which messages it removes from the queue. Messages < WM_HOTKEY are removed from the queue and processed, whilst other messages are left in the queue until the critical thread finishes. This ListView problem goes something like:
  • You start a Critical thread.
  • User clicks on the ListView, sending it a WM_LBUTTONDOWN message.
  • ListView raises some events and posts them to AutoHotkey's message queue.
  • ListView enters into its own message loop, doing only Microsoft knows what. Probably checking whether the user is initiating drag-drop or the selection marquee.
  • ListView's message loop retrieves and dispatches each message, calling AutoHotkey's MainWindowProc().
  • MainWindowProc() knows that it only gets called for those messages when some other message loop is running; therefore, it posts the message back into the queue and calls MsgSleep() to handle the message.
  • MsgSleep() sees that the current thread is uninterruptible, so it applies a filter and only handles messages < WM_HOTKEY. In other words, it probably does nothing.
  • Control returns to ListView's message loop, which sees the message again and dispatches it back to MainWindowProc().
  • MainWindowProc() posts the message back into the queue, etc.
In theory, this can happen with other message loops, like those run by modal dialogs or menus. MsgBox and other AutoHotkey dialogs work around the issue by making the current thread interruptible. Menus work around it by setting a flag which causes certain messages to be discarded rather than buffered.

I couldn't reproduce the problem with DllCall("MessageBox"...), so I'd guess that it depends on exactly what the active message loop does. Discarding GUI events while the thread is uninterruptible and some other message loop (such as the ListView's) is running avoids the problem, but it goes against the documented behaviour of buffering events. (Although discarding the events is better than freezing up.) Unfortunately, it also breaks some other scripts, such as my MessageBox test script, where the event correctly remains buffered until the critical thread completes. (It's possible that the event was actually being re-posted repeatedly, but this did not cause visible CPU usage.)

So in short, the problem is a design flaw of AutoHotkey in combination with the ListView, and only applies to Critical threads. If I remove Critical, your test script works just fine. Adding the following also works, reaffirming that the problem is triggered by LButton handling in the ListView (only tested with your second test script):

Code: Select all

OnMessage(0x201, "OnLButtonDown")
;...
OnLButtonDown(wParam, lParam, msg, hwnd) {
    if (A_GuiControl != "ListControl")
        return
    static LVM_SUBITEMHITTEST := 0x1039
    VarSetCapacity(hti, 24, 0)
    NumPut(lParam & 0xFFFF, hti, 0, "short")
    NumPut(lParam >> 16, hti, 4, "short")
    SendMessage LVM_SUBITEMHITTEST, 0, &hti,, ahk_id %hwnd%
    if (r := NumGet(hti, 12, "int") + 1) {
        GuiControl Focus, ListControl
        LV_Modify(0, "-Select -Focus")
        LV_Modify(r, "Select Focus")
        return true
    }
}
Known issue: It prevents header clicks.
The reason I added the Sleep is because I suspected that Critical is not atomic and doesn't come into effect instantly,
Critical comes into effect instantly; however, calling Sleep before Critical will flush any messages out of the queue. If you disable the control's g-label but there are already messages of the wrong type in the queue, the deadlock can still occur. In this case "the wrong type" probably means GUI event messages, menu item click messages and WM_TIMER. I think hotkey, hotstring and clipboard change messages are essentially discarded if the thread is critical (and someone else's message loop is running).
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Critical thread gets interuped and enters in a deadlock

06 Feb 2015, 20:34

This sounds to be similar to the problems with custom draw ListView scripts: High CPU usage while unresponsive until the window looses the focus. As far as I remember it only happens after mouse actions on the header. Any chance to fix this issue?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

06 Feb 2015, 23:13

It's probably the same issue, and with the same workarounds as mentioned above.

The chance is somewhere between 0% and 100%. The only simple fix breaks some scripts, as I mentioned, and effectively reduces Critical to the same functionality as Thread Interrupt under some circumstances (by preventing buffering of messages). You may as well just not use Critical.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Critical thread gets interuped and enters in a deadlock

07 Feb 2015, 03:05

Custom drawing by monitoring WM_NOTIFY messages does not work without Critical. Critical, 500 seems to be a reasonable compromise, though none of the actions will need that time to finish. Also, I already tried to prevent header actions like resizing or reordering columns and sorting in some of my scripts, but the users won't accept this. Are you sure that it isn't related to the special ListView message handling?

Another question, how does SendMessage work when used within critical treads which won't be interrupted.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

07 Feb 2015, 17:52

Are you sure that it isn't related to the special ListView message handling?
My explanation wasn't detailed enough? It's obviously related, in that the issue is about message handling and happens when you click a ListView. But no, the special ListView message handling is not the cause - I verified by disabling it.
Another question, how does SendMessage work when used within critical treads which won't be interrupted.
The thread is interrupted. Only posted messages can be buffered.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Critical thread gets interuped and enters in a deadlock

11 Mar 2015, 11:39

Ran again into this ListView issue and spent some time on searching. Seems that I now understand a bit more. WM_USER+20 / 0x0414 is the message number used for AHK_GUI_ACTION posted to the script's message loop to pass events to the corresponding event labels. Seemingly this is working without visible side effects for all controls except ListViews.
Default List-View Message Processing wrote:WM_LBUTTONDOWN

Processed in different ways depending on whether a click or drag operation is being initiated. To determine which operation is involved, the list-view control enters a modal message loop until either the button is released or the mouse is moved.
In the case of a click, the list-view control might change which item has the focus and which items are selected, taking into account the cursor position, the state of the SHIFT and CTRL keys, and so on. Then the list-view control sends its parent window an NM_CLICK (list view) notification code.

If dragging begins over an item, the list-view control selects and sets the focus to the item. Then it sends an LVN_BEGINDRAG notification code to the parent window. The parent window is responsible for actually carrying out the drag operation.

If dragging begins over the window background, the list-view control enters another modal message loop, enabling the user to form a rectangle by dragging the mouse. Items within the rectangle are selected.

Source
The following is a simple test script which will show the issue on every left click on my system:

Code: Select all

#NoEnv
SetBatchLines, -1
Gui, Add, ListView, w400 r5 AltSubmit -ReadOnly vLV_Var gLV_Label hwndHLV, Column 1 ; gLV_Label
Loop, 5
   LV_Add("", "Item " . A_Index)
Gui, Show, , WantReturn
SubclassControl(HLV, "LV_SubclassProc")
Return

GuiClose:
ExitApp

LV_Label:
If (A_GuiEvent == "K") && (A_EventInfo = 13)
   ToolTip, %A_ThisLabel%: You pressed Return!
If (A_GuiEvent == "Normal")
   ToolTip, %A_ThisLabel%: Left Click!
If (A_GuiEvent == "DoubleClick")
   ToolTip, %A_ThisLabel%: Left DoubleClick
Return

LV_SubclassProc(H, M, W, L, I, D) {
   Critical
   If (M = 0x0087) && (W = 13) ; WM_GETDLGCODE && VK_RETURN
      Return 0x0004 ; DLGC_WANTALLKEYS
   ; Uncomment the next two lines to prevent the issue <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   ; If (M = 0x0201)
      ; PostMessage, 0x0202, W, L, , ahk_id %H%
   Return DllCall("Comctl32.dll\DefSubclassProc", "Ptr", H, "UInt", M, "Ptr", W, "Ptr", L)
}

; ======================================================================================================================
; SubclassControl    Installs, updates, or removes the subclass callback for the specified control.
; Parameters:        HCTL     -  Handle of the control.
;                    FuncName -  Name of the callback function as string.
;                                If you pass an empty string, the subclass callback will be removed.
;                    Data     -  Optional pointer-sized (unsigned) integer value passed to the callback function.
; Return value:      Non-zero if the subclass callback was successfully installed, updated, or removed;
;                    otherwise, False.
; Remarks:           The callback function must have exactly six parameters, see
;                    SUBCLASSPROC -> msdn.microsoft.com/en-us/library/bb776774(v=vs.85).aspx
; ======================================================================================================================
SubclassControl(HCTL, FuncName, Data := 0) {
   Static ControlCB := []
   HCTL += 0
   If Controls[HCTL] {
      DllCall("RemoveWindowSubclass", "Ptr", HCTL, "Ptr", ControlCB[HCTL], "Ptr", HCTL)
      DllCall("GlobalFree", "Ptr", Controls[HCTL], "Ptr")
      Controls.Remove(HCTL, "")
      If (FuncName = "")
         Return True
   }
   If !DllCall("IsWindow", "Ptr", HCTL)
   || !IsFunc(FuncName)
   || (Func(FuncName).MaxParams <> 6)
   || !(CB := RegisterCallback(FuncName, , 6))
      Return False
   If !DllCall("SetWindowSubclass", "Ptr", HCTL, "Ptr", CB, "Ptr", HCTL, "Ptr", Data)
      Return (DllCall("GlobalFree", "Ptr", CB, "Ptr") & 0)
   Return (ControlCB[HCTL] := CB)
}
/*
SubclassProc(HWND, Msg, wParam, lParam, ID, Data) {
   ; Special message handling ...
   Return DllCall("DefSubclassProc", "Ptr", HWND, "UInt", Msg, "Ptr", wParam, "Ptr", lParam)
}
*/
It seems that the ListView is missing the WM_LBUTTONUP notification for any reason. If you uncomment the handling of WM_LBUTTONDOWN within the subclass callback and post the message manually, the issue disappears.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

11 Mar 2015, 17:11

I'd hardly call any script that uses window subclassing "simple".

It's still the same issue as what I explained earlier, and still can be avoided by not making the thread Critical.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Critical thread gets interuped and enters in a deadlock

12 Mar 2015, 02:08

Yes, but what happens with the WM_LBUTTONUP notification when the button is released? Do you think it's a Windows bug?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

12 Mar 2015, 07:25

How would I know?

As far as I can tell using Spy++, after the initial deadlock-causing WM_LBUTTONDOWN, WM_LBUTTONUP is never posted to any of the script's windows.
zcooler
Posts: 455
Joined: 11 Jan 2014, 04:59

Re: Critical thread gets interuped and enters in a deadlock

28 Mar 2015, 11:09

This issue is definitely in the higher plane of the "pain in the neck" category and it also prevents AHK users from utilizing cool features such as customized tooltip guis launched by mousehover over treeview items. Critical has to be used otherwise the amount of lost events are too many. The lock-up happens if left click and gui show correlates at the exact same moment and behaves exactly as described earlier in this thread. Right click can also be used to reproduce the error. One cannot release software with these kind of lock-ups without lose face. It gets pretty problematic if the only workaround is to avoid using Critical, cuz that would leave the feature almost non-working. In that case I rather scrap the feature entirely.

Hopefully this issue can be reviewed again?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Critical thread gets interuped and enters in a deadlock

28 Mar 2015, 18:22

Using Critical is not the only workaround. I demonstrated earlier that you can avoid it by handling mouse clicks yourself. Another workaround is to prevent the script from checking for messages at all, by using Critical N (where N is long enough for the thread to complete) and avoiding Sleep or any command which waits.

The problem arises because the program is required to process some messages but leave others in the queue, while the ListView (or other control or message loop) probably requires some of those messages which the program is designed to keep queued. I see it as somewhat contradictory using Critical and then also expecting the GUI to remain interactive/responsive.

Most single-threaded programs or languages do not have these issues because they generally do not "multiplex" the message loop into the running thread (i.e. checking for messages in between execution of lines of code). Messages would be checked only at specific times controlled by whatever code is running, like when Application.DoEvents() is called in a .NET program.

As for "reviewing" the issue again, no, I've wasted too many hours already on this issue without particular progress, despite that it's never been of any personal importance to me. Anyone and everyone else is welcome to find a solution if they are able.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: haomingchen1998, robodesign and 246 guests