Page 1 of 1

Thread state

Posted: Wed Jun 05, 2013 3:22 am
by Blankname
I'm trying to check if a thread is suspended or not, and can't seem to get the code I wrote to work.

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 0) = #WAIT_ABANDONED
    PrintN("Thread Suspended")
  EndIf
  Timed = ElapsedMilliseconds()-Timer
  If Timed > 5000
    PauseThread(Thread)
  EndIf
ForEver

Re: Thread state

Posted: Wed Jun 05, 2013 6:20 am
by Demivec
Blankname wrote:I'm trying to check if a thread is suspended or not, and can't seem to get the code I wrote to work.
#WAIT_ABANDONED is for a mutex object.

Re: Thread state

Posted: Wed Jun 05, 2013 6:43 am
by RASHAD
Not very accurate because you are using many delays
And you are not suppose to use consecutive PauseThread()

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 10000) = #WAIT_TIMEOUT	
    PrintN("Thread Suspended")
  EndIf
  Timed = ElapsedMilliseconds()-Timer
  If Timed > 5000 And pause = 0
    PauseThread(Thread)
    pause = 1
  EndIf
ForEver


Re: Thread state

Posted: Wed Jun 05, 2013 7:46 am
by Blankname
RASHAD wrote:Not very accurate because you are using many delays
And you are not suppose to use consecutive PauseThread()

Code: Select all

Procedure MainThread(parameter)
  Repeat
    Delay(1000)
    PrintN("Thread Message")
  ForEver
EndProcedure

OpenConsole()
Thread = CreateThread(@MainThread(), 1)
Timer = ElapsedMilliseconds()

Repeat
  Delay(1000)
  If WaitForSingleObject_(ThreadID(Thread), 10000) = #WAIT_TIMEOUT	
    PrintN("Thread Suspended")
  EndIf
;  Timed = ElapsedMilliseconds()-Timer
;  If Timed > 5000 And pause = 0
;    PauseThread(Thread)
;    pause = 1
  EndIf
ForEver

It ends up spurting "Thread Suspended" every 10 seconds when the timeout expires if you comment out the pausing. GetLastError_() returns 6 "Invalid Handle".

Re: Thread state

Posted: Wed Jun 05, 2013 10:18 am
by Demivec
Wouldn't it be easier to just record whether the thread is paused in a variable (or array, list, etc.) and then check that for its status?

Re: Thread state

Posted: Wed Jun 05, 2013 10:59 am
by RASHAD
As Demivec stated you can use some other way to get it like Flag
Unfortunately WaitForSingleObject_() respond only for #WAIT_TIMEOUT event
That is how Fred designed CreateThread()
I guess you want a message when the Thread is paused or resumed instantly

Re: Thread state

Posted: Wed Jun 05, 2013 7:23 pm
by Blankname
RASHAD wrote:As Demivec stated you can use some other way to get it like Flag
Unfortunately WaitForSingleObject_() respond only for #WAIT_TIMEOUT event
That is how Fred designed CreateThread()
I guess you want a message when the Thread is paused or resumed instantly
I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.

Re: Thread state

Posted: Wed Jun 05, 2013 8:15 pm
by RichAlgeni
I use event handles to accomplish what you want. First create the events, I store them in dimensioned arrays:

Code: Select all

For threadNumber=0 To numberThreads
    thisEvent(threadNumber) = CreateEvent_(0, 0, 0, #ProgramName + "_Event_" + Str(threadNumber))
Next
Then I create threads for each event:

Code: Select all

For threadNumber=0 To numberThreads
    CreateThread(@ProcessRQST(), threadNumber)
Next
Here are the procedures, waiting forever:

Code: Select all

Procedure.i ProcessRQST(requestNumber.i)
    Repeat
        WaitForSingleObject_(thisEvent(requestNumber), #INFINITE)
        ...
The I can call the Windows API function to trigger the event:

Code: Select all

SetEvent_(thisEvent(threadToUse))
To end the process, I just set a global variable ShutDownNow to #True, then fire all of the events. If ShutDownNow is #True, the threaded procedures end.

Re: Thread state

Posted: Wed Jun 05, 2013 10:21 pm
by jassing
Blankname wrote:I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.
Is "the main thread" the executable program being run, and it creates the "checker threads"?
If so, if the exe (and thus, 'the main thread') ends/exits/errors out/crashes, the "checker threads" will die with it.

Re: Thread state

Posted: Mon Jun 10, 2013 10:41 am
by Blankname
jassing wrote:
Blankname wrote:I'm spawning a couple of "checker threads" that's sole purpose is to make sure the main thread hasn't ended or been suspended.
Is "the main thread" the executable program being run, and it creates the "checker threads"?
If so, if the exe (and thus, 'the main thread') ends/exits/errors out/crashes, the "checker threads" will die with it.
I'm spawning three new threads on AttachProcess(), one is the main executed code and the other two are the checker threads to make sure the first thread is running.

Re: Thread state

Posted: Tue Jun 11, 2013 8:25 am
by Blankname
RichAlgeni wrote:I use event handles to accomplish what you want. First create the events, I store them in dimensioned arrays:

Code: Select all

For threadNumber=0 To numberThreads
    thisEvent(threadNumber) = CreateEvent_(0, 0, 0, #ProgramName + "_Event_" + Str(threadNumber))
Next
Then I create threads for each event:

Code: Select all

For threadNumber=0 To numberThreads
    CreateThread(@ProcessRQST(), threadNumber)
Next
Here are the procedures, waiting forever:

Code: Select all

Procedure.i ProcessRQST(requestNumber.i)
    Repeat
        WaitForSingleObject_(thisEvent(requestNumber), #INFINITE)
        ...
The I can call the Windows API function to trigger the event:

Code: Select all

SetEvent_(thisEvent(threadToUse))
To end the process, I just set a global variable ShutDownNow to #True, then fire all of the events. If ShutDownNow is #True, the threaded procedures end.
WaitForSingleObject waits until a thread is finished tho doesn't it? To clarify what I am doing I will post a example code below. The purpose is for a simple anti-cheat engine for my game, and the purpose for the checker threads it keep players from just simply suspending the main thread (with all the important checks) and bypassing it completely. With a few checker threads constantly monitoring the main thread, it will make it much harder to bypass with software like Process Explorer. Tho it would be better if every thread checked each other.

Code: Select all

Procedure MainThread(Value.i)
  Repeat
    ; All The Main Code
  ForEver
EndProcedure

Procedure CheckerThread(Value.i)
  Repeat
    ; Checks If Main Thread Is Still Active + Running (Not Suspended)
    ; Checks If Checker Thread 1 + 2 Is Still Active + Running (Not Suspended)
  ForEver
EndProcedure

ProcedureDLL AttachProcess(Instance)
  Thread1 = CreateThread(@MainThread(), 1)
  Thread2 = CreateThread(@CheckerThread(), 2)
  Thread3 = CreateThread(@CheckerThread(), 3)
EndProcedure

Re: Thread state

Posted: Tue Jun 11, 2013 4:22 pm
by RichAlgeni
WaitForSingleObject_(thisEvent(requestNumber), #INFINITE) can be used anywhere, not just in a thread. It waits the amount of time specified in the second parameter. In the above case, it will wait forever, but just until SetEvent_(thisEvent(requestNumber)) is executed, in which case it will go on it's way. You can also use a timer in the second parameter:

http://msdn.microsoft.com/en-us/library ... s.85).aspx

Once the timer expires, execution will continue in the same way as if an event fired. You don't need to use SetEvent, unless you want the execution to continue for any reason before a time expires.

You can use this in your checker threads to periodically wake up and check the main thread.

Re: Thread state

Posted: Wed Jun 12, 2013 5:22 am
by Blankname
This works for me, ResumeThread doesn't return true until the specified thread is paused (suspended). So I don't have to suspend the thread at all, this is a much more efficient way to check if a thread is suspended (plus it just resumes it if it was).

Code: Select all

Global Thread1, Thread2

Procedure MainThread(Value.i)
  Repeat
    PrintN("Thread Message [" + Str(Random(99, 10)) + "]")
    Delay(1000)
  ForEver
EndProcedure

Procedure CheckerThread(Value.i)
  Repeat
    If IsThread(Thread1)
      If ResumeThread(Thread1)
        PrintN("Thread Suspended!")
      EndIf
    Else
      PrintN("Thread Killed!")
    EndIf
    Delay(1000)
  ForEver
EndProcedure

OpenConsole()

Thread1 = CreateThread(@MainThread(), 1)
Thread2 = CreateThread(@CheckerThread(), 2)

Repeat
  Delay(1)
ForEver

Re: Thread state

Posted: Wed Jun 12, 2013 5:26 pm
by RichAlgeni
Very good!