Skip to content(if available)orjump to list(if available)

How to stop Linux threads cleanly

How to stop Linux threads cleanly

32 comments

·October 15, 2025

leeter

I'm reminded of Raymond Chen's many many blogs[1][2][3](there are a lot more) on why TerminateThread is a bad idea. Not surprised at all the same is true elsewhere. I will say in my own code this is why I tend to prefer cancellable system calls that are alertable. That way the thread can wake up, check if it needs to die and then GTFO.

[1] https://devblogs.microsoft.com/oldnewthing/20150814-00/?p=91...

[2] https://devblogs.microsoft.com/oldnewthing/20191101-00/?p=10...

[3] https://devblogs.microsoft.com/oldnewthing/20140808-00/?p=29...

there are a lot more, I'm not linking them all here.

the_duke

For interrupting long-running syscalls there is another solution:

Install an empty SIGINT signal handler (without SA_RESTART), then run the loop.

When the thread should stop:

* Set stop flag

* Send a SIGINT to the thread, using pthread_kill or tgkill

* Syscalls will fail with EINTR

* check for EINTR & stop flag , then we know we have to clean up and stop

Of course a lot of code will just retry on EINTR, so that requires having control over all the code that does syscalls, which isn't really feasible when using any libraries.

EDIT: The post describes exactly this method, and what the problem with it is, I just missed it.

rostayob

This option is described in detail in the blog posts, with its associated problems, see this section: https://mazzo.li/posts/stopping-linux-threads.html#homegrown... .

the_duke

Ah, fair, I missed it when reading the post because the approach seemed more complicated.

loeg

If you can swing it (don't need to block on IO indefinitely), I'd suggest just the simple coordination model.

  * Some atomic bool controls if the thread should stop or not;
  * The thread doesn't make any unbounded wait syscalls;
  * And the thread uses pthread_cond_wait (or equivalent C++ std wrappers) in place of sleeping while idle.
To kill the thread, set the stop flag and cond_signal the condvar. (Under the hood on Linux, this uses futex.)

asveikau

Relying heavily on a check for an atomic bool is prone to race conditions. I think it's cleaner to structure the event loop as a message queue and have a queued message that indicates it's time to stop.

null

[deleted]

PaulDavisThe1st

Every event loop is subject to the blocked-due-to-long-running-computation issue. It bites ...

null

[deleted]

OskarS

The tricky part is really point 2 there, that can be harder than it looks (e.g. even simple file I/O can be network drives). Async IO can really shine here, though it’s not exactly trivial designing async cancelletion either.

vlovich123

This seems like a lot of work to do when you have signalfd, no? That + async and non blocking I/O should create the basis of a simple thread cancellation mechanism that exits pretty immediately, no?

ibejoeb

libcurl dealt with this a few months ago, and the sentiment is about the same: thread cancellation in glibc is hairy. The short summary (which I think is accurate) is that an hostname query via libnss ultimately had to read a config file, and glibc's `open` is a thead cancellation point, so if it's canceled, it'll won't free memory that was allocated before the `open`.

The write-up is on how they're dealing with it starts at https://eissing.org/icing/posts/pthread_cancel/.

teddyh

Off-Topic: I surprised myself by liking the web site design. Especially the font.

ethin

This was a fun read, I didn't know about rseq until today! And before this I reasonably assumed that the naive busy-wait thing would typically be what you'd do in a thread in most circumstances. Or that at least most threads do loop in that manner. I knew that signals and such were a problem but I didn't think just wanting to stop a thread would be so hard! :)

Hopefully this improves eventually? Who knows?

a-dub

this stuff always seemed a mess. in practice i've always just used async io (non-blocking) and condition variables with shutdown flags.

trying to preemptively terminate a thread in a reliable fashion under linux always seemed like a fool's errand.

fwiw. it's not all that important, they get cleaned up at exit anyway. (and one should not be relying on operating system thread termination facilities for this sort of thing.)

quotemstr

pthread cancelation ends up not being the greatest, but it's important to represent it accurately. It has two modes: asynchronous and deferred. In asynchronous mode, a thread can be canceled any time, even in the middle of a critical section with a lock held. However, in deferred mode, a thread's cancelation can be delayed to the next cancelation point (a subset of POSIX function calls basically) and so it's possible to make that do-stuff-under-lock flow safe with cancelation after all.

That's not to say people do or that it's a good idea to try.

rostayob

Cancellation points and cancellability state are discussed in the post. In a C codebase that you fully control pthread cancellation _can_ be made to work, but if you control the whole codebase I'd argue you're better off just structuring your program so that you yield cooperatively frequently enough to ensure prompt termination.

hulitu

> How to stop Linux threads cleanly

kill -HUP ?

harvie

while (true) { if (stop) { break; } }

If there only was a way to stop while loop without having to use extra conditional with break...

OskarS

Feel free to read the article before commenting.

f1shy

I’ve read it, and I found nothing to justify that piece of code. Can you please explain?

bartvk

The while loop surrounds the whole thread, which does multiple tasks. The conditional is there to surround some work completing in a reasonable time. That's how I understood, at least.