Recent

Author Topic: Force thread termination  (Read 1109 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Force thread termination
« on: April 10, 2021, 01:11:03 am »
How can I force a thread to terminate?

Consider this :

Code: Pascal  [Select][+][-]
  1. procedure TMyThread.Execute;
  2. begin
  3.   Sleep(10000000);
  4. end;
  5.  

MyThread.Terminate will still wait for Sleep to finish.
Windows 10
Laz 2.0.10
FPC 3.2.0

y.ivanov

  • Jr. Member
  • **
  • Posts: 98
Re: Force thread termination
« Reply #1 on: April 10, 2021, 01:37:24 am »
Win: TerminateThread(), Linux: pthread_cancel(), pthread_kill()

But it is very extreme way and may have very bad consequences.

Why just not write the Execute method in such a way it checks Terminated more often?
Code: Pascal  [Select][+][-]
  1. procedure TMyThread.Execute;
  2. var
  3.   I: Integer;
  4. begin
  5.   for I := 1 to 10000 do
  6.     if not Terminated then
  7.       Sleep(1000) else
  8.       break;
  9. end;

 

jamie

  • Hero Member
  • *****
  • Posts: 4452
Re: Force thread termination
« Reply #2 on: April 10, 2021, 01:41:01 am »
It sure will

The idea is to put your EXC code into a loop testing the TERMINATE flag in that loop..
Code: Pascal  [Select][+][-]
  1. Procedure TMythread.Execute;
  2. Begin
  3.  While not Terminate Do
  4.   begin
  5.     your code..
  6.   End;
  7.  

And even somewhere in your code you can also test the terminate and call EXIT.

so outside threads only need to set the Terminated := True;

The only true wisdom is knowing you know nothing

Warfley

  • Sr. Member
  • ****
  • Posts: 449
Re: Force thread termination
« Reply #3 on: April 10, 2021, 03:48:18 am »
The problem with forcefully stopping a thread is that no cleanup procedure is executed, so any created objects, opened files, acquired locks, or generally allocated resources will not be freed.

Therefore checking for a termination flag is usually the best practice. That said, if you can't redesign your code around that (maybe you call blocking library code or similar you just cant avoid) there is another way, using signals.

You must register a signal handler, which will perform cleanup and then forcefully kill the thread. For this to work, all acquired resources must be accessible from the handler, meaning no local variables that reference shared resources (class instances, files, heap pointer, etc). No managed types (strings, arrays) should anywhere in that thread. When accessing the shared objects, lock these operations by masking out the signal, but keep these locks as small as possible, othereise you cant force terminate.
If you can do that, this will be fine. That said, code that does not contain strings, arrays or temporary classes is probably not that useful

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Re: Force thread termination
« Reply #4 on: April 10, 2021, 04:16:32 am »
Thanks all.

@Warfley - do you have a small sample?

I use HTTPSend to get / download info from the net (in a thread) and sometimes it gets stuck. That's why I need to kill it.
« Last Edit: April 10, 2021, 05:00:38 am by pcurtis »
Windows 10
Laz 2.0.10
FPC 3.2.0

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7095
  • Debugger - SynEdit - and more
    • wiki
Re: Force thread termination
« Reply #5 on: April 10, 2021, 06:45:37 am »
Even the memory is shared between threads. Pretty sure if the interrupt comes in the wrong moment (race condition), it can corrupt the entire memory for all threads in the process. Or leave a lock in place preventing other threads from doing any mem alloc.

So unless your thread is most basic, and has only a fixed amount of pre-alloc mem, when you kill the thread, you have a chance to corrupt the entire process.

If you must do the hard shutdown, consider running the task in a separate process instead. (and kill that process, if needed)

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: Force thread termination
« Reply #6 on: April 10, 2021, 07:26:59 am »
@pcurtis

Quote
I use HTTPSend to get / download info from the net (in a thread) and sometimes it gets stuck. That's why I need to kill it.
If you are working with FpHTTPClient please read this thread: https://forum.lazarus.freepascal.org/index.php/topic,38472.0.html
Briefly: FpHTTPClient has a Terminate method which will force FPHttpClient to abort immediately after the current chunk is received/send.

I did not check, but I'm almost certain that similar mechanisms are implemented in Indy and Synapse too.

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Re: Force thread termination
« Reply #7 on: April 10, 2021, 09:37:29 am »
OK, but what if the chunk is never sent / recieved?
« Last Edit: April 10, 2021, 09:49:45 am by pcurtis »
Windows 10
Laz 2.0.10
FPC 3.2.0

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1441
  • Former Delphi 1-7, 10.2 user
Re: Force thread termination
« Reply #8 on: April 10, 2021, 09:48:17 am »
Why not use a timeout? For example:

Code: Pascal  [Select][+][-]
  1. function Read_URL_GET(url:string):string;
  2.     begin
  3.     with TFPHTTPClient.Create(nil) do
  4.       try
  5.         ConnectTimeout := 3000;   // 3 second timeout
  6.         Read_URL_GET:= Get(url);
  7.       except
  8.         on E:Exception do
  9.            begin
  10.               Read_URL_GET:= 'ERROR';
  11.            end;
  12.       end;
  13.     end;
Lazarus 2.1 r65061 FPC 3.3.1 r49223 macOS 10.14.6 Xcode 11.3.1
Lazarus 2.1 r65070 FPC 3.3.1 r49223 macOS 11.2.3 aarch64 Xcode 12.4
Lazarus 2.1 r61574 FPC 3.3.1 r42318 FreeBSD 12.1 amd64 VMware VM
Lazarus 2.1 r61574 FPC 3.0.4 Ubuntu 20.04 Parallels VM
Lazarus 2.0.10 FPC 3.2.0 Win10 Parallels VM

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Re: Force thread termination
« Reply #9 on: April 10, 2021, 09:51:56 am »
Can the timeout be triggered if no data is rx/tx for say 20secs.?

So if there is no rx/tx activity for x secs it timesout
« Last Edit: April 10, 2021, 09:55:18 am by pcurtis »
Windows 10
Laz 2.0.10
FPC 3.2.0

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: Force thread termination
« Reply #10 on: April 10, 2021, 10:10:40 am »
@pcurtis
Quote
OK, but what if the chunk is never sent / recieved?
As @trev already mentioned you have to use FPHTTPClient.ConnectTimeout combined with TFPHTTPClient.Terminate. You have two cases:
1. Server is offline, ConnectTimeout will do the job.
2. Server is online but is very slow, Terminate will do the job

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Re: Force thread termination
« Reply #11 on: April 10, 2021, 10:18:17 am »
is this luxury available in Synapse?
Windows 10
Laz 2.0.10
FPC 3.2.0

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: Force thread termination
« Reply #12 on: April 10, 2021, 10:44:16 am »
Quote
is this luxury available in Synapse?
I did take a quick look to THTTPSend(unit httpsend.pas). It has a KeepAliveTimout property, you can read more here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive
Also the timeout for the TCPBlockSocket, which does the communication with the server, is set to 90000 in the constructor.

Warfley

  • Sr. Member
  • ****
  • Posts: 449
Re: Force thread termination
« Reply #13 on: April 10, 2021, 05:13:14 pm »
Even the memory is shared between threads. Pretty sure if the interrupt comes in the wrong moment (race condition), it can corrupt the entire memory for all threads in the process. Or leave a lock in place preventing other threads from doing any mem alloc.

So unless your thread is most basic, and has only a fixed amount of pre-alloc mem, when you kill the thread, you have a chance to corrupt the entire process.

If you must do the hard shutdown, consider running the task in a separate process instead. (and kill that process, if needed)
It is possible to do, if you lock the shared access by masking out signals. A signal arriving while masked out will be fired as soon as it is enabled again. So something like this would work perfectly fine:
Code: Pascal  [Select][+][-]
  1. disableSignal(signum);
  2. x := GetMem(size);
  3. enableSignal(signum);
  4. ...
  5. disableSignal(signum);
  6. FreeMem(x);
  7. x := Nil;
  8. enableSignal(signum);
  9.  
  10. procedure SignalHandler(signum: Integer);
  11. begin
  12.   if Assigned(x) then
  13.     FreeMem(x);
  14.   x := Nil;
  15.   KillThread;
  16. end;

Of course there should be try-finally blocks and stuff.

But yeah, this is a very limiting approach, as all dynamic resources must be accessible through global variables. Also most fpc code relies on managed types, which the user can not handle themselves.

I would highly recommend against this practice, unless you have full control over your code and know exactly what is going on on the memory level. And even then it hardly seems a good choice because it is pretty easy to do it wrong

pcurtis

  • Hero Member
  • *****
  • Posts: 537
Re: Force thread termination
« Reply #14 on: April 11, 2021, 04:39:09 am »
OK, thanks. I'll give my code a rethink.
Windows 10
Laz 2.0.10
FPC 3.2.0

 

TinyPortal © 2005-2018