Block on END

Just starting out? Need help? Post your questions and find answers here.
ALAN-MHz
User
User
Posts: 68
Joined: Fri Jul 29, 2005 11:47 am

Block on END

Post by ALAN-MHz »

Dear all, i've a strange problem on a software compiled with latest v6.02 LTS, sometimes do not close on end remain process blocked, to better explain is a window that on event show a messagerequester for confirm to close, if user confirm the command "end" is called, i've also tried to free all resources before calling "end", i've also tried to insert a "calldebugger" before the end to better check, calldebugger is called and when i step on "end" program do not close also in IDE and i cannot pause it, is completely locked.

The problem is also randomic in both compiled and in IDE, sometimes software close without problem, sometimes i've got this problem

Of couse killing from task manager resolve the problem.

Any ideas ?
User avatar
jacdelad
Addict
Addict
Posts: 1992
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Block on END

Post by jacdelad »

Me trying to help you without any hint of code:
Image
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Block on END

Post by mk-soft »

Which operating system.
macOS and Linux do not like it when threads are still running in the background.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
ALAN-MHz
User
User
Posts: 68
Joined: Fri Jul 29, 2005 11:47 am

Re: Block on END

Post by ALAN-MHz »

Windows 11

Code: Select all

    If MessageRequester ( Softname , "Sure to close ?" , #PB_MessageRequester_YesNo ) = #PB_MessageRequester_Yes
     If IsThread ( CleanThread )
      KillThread ( CleanThread )
     EndIf
     If IsThread ( AutoPilotThread )
      KillThread ( AutoPilotThread )
     EndIf
     If IsThread ( AutoRetryThread )
      KillThread ( AutoRetryThread )
     EndIf
     UpdateDB ()
     UpdateFile ()
     If IsDatabase ( 0 )
      CloseDatabase ( 0 )
     EndIf
     If IsDatabase ( 1 )
      CloseDatabase ( 1 )
     EndIf
     Delay ( 1000 )
     ReleaseMutex_ ( Mutex )
     End
    EndIf
User avatar
jacdelad
Addict
Addict
Posts: 1992
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Block on END

Post by jacdelad »

Don't use KillThread, instead set a global variable or something and handle it within the thread!
Also, your code isn't runnable.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
ALAN-MHz
User
User
Posts: 68
Joined: Fri Jul 29, 2005 11:47 am

Re: Block on END

Post by ALAN-MHz »

jacdelad wrote: Mon Jul 24, 2023 2:44 pm Don't use KillThread, instead set a global variable or something and handle it within the thread!
Also, your code isn't runnable.
i cannot use global variable to manage the thread because they are totally indipendent from main code and contain a lot of delay for processing jobs scheduled, if i set a variable for inform the thread that must end without kill i need to wait the last delay that is currently running in the thread, for example if sleep is 1 minute so the main window must wait 1 minute to close and this is totally unacceptable.

My code isn't runnable but work perfectly except the program end ? really interesting, so explain me what's wrong
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Block on END

Post by mk-soft »

Build a loop with 100ms delay and query the end of the programm in this loop.

Where is a owner of Mutex ?
MSDN:
Remarks
The ReleaseMutex function fails if the calling thread does not own the mutex object.
A thread obtains ownership of a mutex either by creating it with the bInitialOwner parameter set to TRUE or by specifying its handle in a call to one of the wait functions. When the thread no longer needs to own the mutex object, it calls the ReleaseMutex function so that another thread can acquire ownership.
A thread can specify a mutex that it already owns in a call to one of the wait functions without blocking its execution. This prevents a thread from deadlocking itself while waiting for a mutex that it already owns. However, to release its ownership, the thread must call ReleaseMutex one time for each time that it obtained ownership (either through CreateMutex or a wait function).
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
ALAN-MHz
User
User
Posts: 68
Joined: Fri Jul 29, 2005 11:47 am

Re: Block on END

Post by ALAN-MHz »

it's the main thread that initialize the mutex after the global variable declaration

do you think that thread can cause the end failure ?

it's also strange that also the debugger freeze

testing:

Code: Select all

    If MessageRequester ( Softname , "Sure to close ?" , #PB_MessageRequester_YesNo ) = #PB_MessageRequester_Yes
     CloseThread = #True
     Repeat
      Delay ( 100 )
     Until IsThread ( CleanThread ) = 0 And IsThread ( AutoPilotThread ) = 0 And IsThread ( AutoRetryThread ) = 0
     UpdateDB ()
     UpdateFile ()
     If IsDatabase ( 0 )
      CloseDatabase ( 0 )
     EndIf
     If IsDatabase ( 1 )
      CloseDatabase ( 1 )
     EndIf
     ReleaseMutex_ ( Mutex )
     CallDebugger
     End
    EndIf
Last edited by ALAN-MHz on Mon Jul 24, 2023 4:00 pm, edited 1 time in total.
User avatar
jacdelad
Addict
Addict
Posts: 1992
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Block on END

Post by jacdelad »

ALAN-MHz wrote: Mon Jul 24, 2023 3:03 pm
jacdelad wrote: Mon Jul 24, 2023 2:44 pm Don't use KillThread, instead set a global variable or something and handle it within the thread!
Also, your code isn't runnable.
i cannot use global variable to manage the thread because they are totally indipendent from main code and contain a lot of delay for processing jobs scheduled, if i set a variable for inform the thread that must end without kill i need to wait the last delay that is currently running in the thread, for example if sleep is 1 minute so the main window must wait 1 minute to close and this is totally unacceptable.

My code isn't runnable but work perfectly except the program end ? really interesting, so explain me what's wrong
But that's the way it will work. Also, you can chop your long delay into shorter delays (and process the rest of your stuff after n-count of processed delays) to be able to process the termination variable.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
mk-soft
Always Here
Always Here
Posts: 6204
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Block on END

Post by mk-soft »

But not the loop when the program ends, but in the thread.

Code: Select all

;-TOP

CompilerIf Not #PB_Compiler_Thread
  CompilerError "Use Compiler Option ThreadSafe"
CompilerEndIf

#ProgramTitle = "Main Window"
#ProgramVersion = "v1.01.2"

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  #MainList
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

; ----

Structure udtMyThread
  ThreadID.i
  Exit.i
  Name.s
  Pause.i
EndStructure

Global.udtMyThread th1, th2

Procedure MyThread(*Data.udtMyThread)
  Protected time
  With *Data
    Debug "Init Thread " + \Name
    Repeat
      ; Working
      Debug "Do any ... " + \Name
      For i = 1 To 100
        ; Check exit
        If \Exit
          Debug "Cancel Thread " + \Name
          Break
        EndIf
        ; Simulate processing
        Delay(8)
      Next
      ; Pause
      time = ElapsedMilliseconds()
      Repeat
        ; Check exit
        If \Exit
          Break 2
        EndIf
        Delay(100)
        If ElapsedMilliseconds() - time > \Pause
          Break
        EndIf
      ForEver
    ForEver
    Debug "Exit Thread " + \Name
  EndWith
EndProcedure

; ----

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
  ; Resize gadgets
  ResizeGadget(#MainList, 0, 0, dx, dy)
EndProcedure

Procedure Main()
  Protected dx, dy
  
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
    ; Menu
    CreateMenu(#MainMenu, WindowID(#Main))
    MenuTitle("&File")
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      MenuItem(#PB_Menu_About, "")
    CompilerElse
      MenuItem(#MainMenuAbout, "About")
    CompilerEndIf
    ; Menu File Items
    
    CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
      MenuBar()
      MenuItem(#MainMenuExit, "E&xit")
    CompilerEndIf
    
    ; StatusBar
    CreateStatusBar(#MainStatusBar, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    ListViewGadget(#MainList, 0, 0, dx, dy)
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
    
    th1\Name = "MyThread 1"
    th1\Pause = 5000
    th1\ThreadID = CreateThread(@MyThread(), @th1)
    Delay(100)
    th2\Name = "MyThread 2"
    th2\Pause = 7500
    th2\ThreadID = CreateThread(@MyThread(), @th2)
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              Break
              
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            CompilerEndIf
              
            Case #MainMenuExit
              PostEvent(#PB_Event_CloseWindow, #Main, #Null)
              
            Case #MainMenuAbout
              MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
              
          EndSelect
          
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #MainList
              Select EventType()
                Case #PB_EventType_Change
                  ;
              EndSelect
              
          EndSelect
          
      EndSelect
    ForEver
    
    th1\Exit = #True
    th2\Exit = #True
    If WaitThread(th1\ThreadID, 5000) = 0
      KillThread(th1\ThreadID)
      Debug "Thread th1 killed"
    EndIf
    If WaitThread(th2\ThreadID, 5000) = 0
      KillThread(th2\ThreadID)
      Debug "Thread th2 killed"
    EndIf
    
  EndIf
  
EndProcedure : Main()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: Block on END

Post by BarryG »

jacdelad wrote: Mon Jul 24, 2023 2:44 pmDon't use KillThread, instead set a global variable or something and handle it within the thread
That won't help when a thread is showing a MessageRequester() or InputRequester(), etc. KillThread() is needed in such cases.
ALAN-MHz
User
User
Posts: 68
Joined: Fri Jul 29, 2005 11:47 am

Re: Block on END

Post by ALAN-MHz »

threads seems more stable with a global variable for closing them, i test more and more times to be sure because as told the problem is randomic

thanks to all for suggestions
Post Reply