Re: [PATCH] signal: Use list_del_init_careful() in flush_sigqueue()

From: Eric W. Biederman

Date: Thu Aug 27 2026 - 15:03:59 EST


Thomas Gleixner <tglx@xxxxxxxxxx> writes:

> On Wed, Aug 26 2026 at 22:29, Eric W. Biederman wrote:
>> Could the posix timers cleanup be moved from __exit_signal in
>> release_task (which is really for cleanup for zombies but has
>> been historically abused because it was the only place that
>> knew when the whole group was dead), into somewhere in do_exit?
>>
>> Say near where hrtimers_cancel and exit_itimers are called.
>
> That's only for the group_dead case in do_exit().
>
> But a single task existing from a process needs to clean up
> task::pending, i.e. signals which are targeted at the exiting task.
>
> The safe and obvious place is to do that is _after_ setting
> task::sighand to NULL because that ensures that no new signal can be
> queued and nothing can touch task::pending anymore.

Not really. Using release_task (which is what is called when a zombie
is reaped) for anything except cleaning up state that a zombie needs is
a bit of a misfeature. Timers should not be active in a zombie.
Signals also should be deactivated long before then.


The obvious place to clean up task::pending i.e. signals is in
exit_signals().

I expect if I read through the history again that I would find that
exit_signals() used to call flush_sigqueue, and that during the addition
of posix thread signal handling flush_sigqueue was moved into
__exit_signal in release_task because knowing if the entire thread group
is dead was not available during that part of 2.5.

We should honor PF_EXITING on a task and simply stop delivering
signals to it. Today the code goes halfway there and does not
set sig-pending after PF_EXITING is set.

There is the goofy case that we need to be able to deliver signals
to the entire process through a zombie thread (in particular a zombie
thread group leader). That goofy case unfortunately means that except
for signals to just the thread we have to deliver signals when
PF_EXITING is set. That goofy case also unfortunately means that
sighand_struct needs to be retained past the point where signals
are delivered.

>> Then perhaps move the posix timer disabling before de_thread?
>
> That does not work because between that and de_thread() any thread of
> the thread group can create a new posix timer unless we prevent that
> somehow in timer_create().
>
> So in any case we need some mechanism in posixtimer related code to
> handle this situation gracefully.

Which is a completely reasonable reason to focus on that mechanism,
and leave the rest alone.


I suspect the current crop of bug finding may keep coming until all of
the weird corner cases in process cleanup, exec, and signal handling are
all sorted out. So figuring out how to make the code make better sense
in the long run appears to be a good idea.

Eric