POSIX has thread cancellation for precisely that reason. Instead of just terminating a thread, it is sent a signal, and can then act on the signal by running various cleanup handlers (pthread_cleanup_push()/pthread_cleanup_pop()). Now, most software is not written to deal with this correctly, and the interactions between thread cancellation and C++ are undefined (glibc makes thread cancellation an asynchronous C++ exception, but this behavior is not guaranteed, and musl for example does not do this), and so destructors can be left unexecuted. But the functionality is there.
AndrewAPrice wrote:
It seems such a trivial function for a kernel to provide - unschedule a running thread and release its stack.
But, what if a thread was holding onto user space locks, or owned allocated memory?
First of all, how does the kernel know where the stack of a thread is? In my OS, the thread stack is only given to the kernel as pointer to the top in the clone() system call. But the kernel doesn't know how long it is. Even if it did know at creation time, it cannot know how large it is later on when the thread finishes (someone might have enlarged it). Besides that, memory is not the only kind of resource a thread can obtain. Files and sockets are another big one.
Korona wrote:
Resource allocation/deallocation on thread termination is not an issue for capability-based systems (as soon as there is one handle to a resource left, it stays alive).
And do you auto-close the resources when a thread is terminated? Then they are not sharable. But at the very least, you cannot do that for memory, because sharing memory is what threads are all about, and so dead memory will be left around after killing a thread.
PeterX wrote:
But I think on the other hand, sometimes it is crucial to stop a program fast. For example if you have made a mistake on the shell or in a script. Or if a tool does something harmful which you didn't expect.
That is what killing a process is for. Killing a thread can leave a process in an unstable state, and the vast majority of programs is not written to cope. Killing a process just ends the entire thing, and then the resource collection on end of process can happen, and then a lot of the resources can get released. Not SysV shared memory, but then, whoever uses that has only themselves to blame, right?