Bug 20730 - Need a way to tell pthread_cancel and pthread_exit don't do the forced unwind
Summary: Need a way to tell pthread_cancel and pthread_exit don't do the forced unwind
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: nptl (show other bugs)
Version: 2.13
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-10-22 19:59 UTC by Bai Yang
Modified: 2016-10-24 10:34 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2016-10-23 00:00:00
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bai Yang 2016-10-22 19:59:28 UTC
I want pthread_cancel and pthread_exit not throw __forced_unwind exception, and there is no need to do the cleanup in our case. e.g.: I just want terminate the thread immediately without ANY cleanup, like the TerminateThread Win32 API. 

As far as I known, behaviors of the musl-libc and CLang libc are both equal to the TerminateThread API.

I understand __forced_unwind is very useful in some cases, but it is clearly unable to adapt to all situations. 

So could we add a new API, let user set the wanted behavior of pthread_cancel and pthread_exit, like: pthread_setcancelmethod(PTHREAD_CANCEL_NO_UNWIND)?

I'm using longjmp to implement the "TerminateThread" behavior now, but I think it is valuable to support it directly by glibc.
Comment 1 Florian Weimer 2016-10-23 08:53:12 UTC
Could you provide more information why you need this?

If we add such a function, it would be essentially broken, leaking resources and generally leaving the process in an undefined state, just like TerminateThread on Windows or java.lang.Thread#stop() on Java.
Comment 2 Bai Yang 2016-10-23 11:21:27 UTC
(In reply to Florian Weimer from comment #1)
> Could you provide more information why you need this?
> 
> If we add such a function, it would be essentially broken, leaking resources
> and generally leaving the process in an undefined state, just like
> TerminateThread on Windows or java.lang.Thread#stop() on Java.

Yes, at least two reasons:
1. "kill a thread" is none involved with c++ exceptions, it disturb the normal exception filtering, catching and processing job. I only see glibc do this, others libc on linux and others OS seems all don't do that.

2. At least in some cases, We want cancel doing a dirty quick abnormal termination for thread, we don't want it execute every distructor of the object because it may be block few minutes, even few hours, e.g.: disconnect from a remote mysql server which network cable has been cutting off. 

Cancel is not a normal stop, we only use this api when the normal one (inform the thread by set a flag or send a message to it, and wait itself stop) can't work. In these situations, we don't trust the thread any more, and think the thread could not finish the clean up within a reasonable duration. 

So, cancel for thread is more like 'kill -9' for process in these use case. I think that's why Windows, musl-libc, CLang libc, java and etc. provide TerminteThread semantic API. glibc also need to provide one to deal with these dirty works.
Comment 3 Florian Weimer 2016-10-24 09:35:57 UTC
(In reply to Bai Yang from comment #2)
> (In reply to Florian Weimer from comment #1)
> > Could you provide more information why you need this?
> > 
> > If we add such a function, it would be essentially broken, leaking resources
> > and generally leaving the process in an undefined state, just like
> > TerminateThread on Windows or java.lang.Thread#stop() on Java.
> 
> Yes, at least two reasons:
> 1. "kill a thread" is none involved with c++ exceptions, it disturb the
> normal exception filtering, catching and processing job. I only see glibc do
> this, others libc on linux and others OS seems all don't do that.

Something like it is required that you can write cancellation handlers using the C++ unwind mechanism.

Adding the function you request would break that.

> 2. At least in some cases, We want cancel doing a dirty quick abnormal
> termination for thread, we don't want it execute every distructor of the
> object because it may be block few minutes, even few hours, e.g.: disconnect
> from a remote mysql server which network cable has been cutting off. 

This is really a fringe case.  Most applications would not be able to cope with the resource leaks (memory and file descriptors).  If resource consumption does not matter, you could just not cancel the thread at all.
Comment 4 Bai Yang 2016-10-24 10:27:24 UTC
(In reply to Florian Weimer from comment #3)
> (In reply to Bai Yang from comment #2)
> > (In reply to Florian Weimer from comment #1)
> > > Could you provide more information why you need this?
> > > 
> > > If we add such a function, it would be essentially broken, leaking resources
> > > and generally leaving the process in an undefined state, just like
> > > TerminateThread on Windows or java.lang.Thread#stop() on Java.
> > 
> > Yes, at least two reasons:
> > 1. "kill a thread" is none involved with c++ exceptions, it disturb the
> > normal exception filtering, catching and processing job. I only see glibc do
> > this, others libc on linux and others OS seems all don't do that.
> 
> Something like it is required that you can write cancellation handlers using
> the C++ unwind mechanism.
> 
> Adding the function you request would break that.

Assume we are using a 3rd party library, which has a TThread clase like:

class TThread 
{
    // ...
    virtual int Entry(void) = 0; // Thread Entry
    virtual void OnUncaughtException(void) throw(); // deal exceptions throw by Entry
}

You can imaging there MUST something like this in the library:
try 
{
    Entry()
}
catch (...)
{
    OnUncaughtException();
}
// ...

It's a common pattern to prevent the exception throw across the thread boundary. And work well with all OS libraries except glibc, because all other systems "libc" (Windows "kernel32", linux musl-libc, linux CLong libc, Solaris, HP-UX, AIX, and etc.) both agree that kill a thread IS NOTING ABOUT A C++ EXCEPTION!

So, this "unique feature" of glibc caused following problems:
1. The 3rd party code may be very difficult to change.
2. A lot of existing codes rely on the 3rd party lib that buy in this pattern need to change, It's huge work.

So, at least give us a option to turn off this glibc "unique feature".

> 
> > 2. At least in some cases, We want cancel doing a dirty quick abnormal
> > termination for thread, we don't want it execute every distructor of the
> > object because it may be block few minutes, even few hours, e.g.: disconnect
> > from a remote mysql server which network cable has been cutting off. 
> 
> This is really a fringe case.  Most applications would not be able to cope
> with the resource leaks (memory and file descriptors).  If resource
> consumption does not matter, you could just not cancel the thread at all.

We can cope it by something like "modeler isolation", or by other methods. Why Windows, Java, musl-libc, CLong libc and a lot of others provide this function? They all wrong, only you are right?

Even if only you know "they all wrong and the world is wrong", you still need to compliance the wrong world, to make other existing codes not broken on your lib. 

You can implement an unconventional default "right action", but at least "compliance the wrong world" through some optional settings.

Of course we can solve this issue by use longjmp, but I still think glibc NEED to give us a way to do the "conventional action".

thanks
Comment 5 Bai Yang 2016-10-24 10:34:33 UTC
And if the user appreciate the current unconventional "unique feature" they just don't need do anything. I'm not requesting you to change the default behaviors, I just request you to add an optional setting to compliance the "conventional action".