Re: [PATCH] task_work: Consume only item at a time while invoking the callbacks.

From: Oleg Nesterov
Date: Wed Feb 26 2025 - 07:51:35 EST


On 02/21, Sebastian Andrzej Siewior wrote:
>
> Yi and syzbot managed to hang the task within task_run().
>
> The problem is
> task_work_run() -> __fput() -> perf_release() ->
> perf_event_release_kernel() -> _free_event() ->
> perf_pending_task_sync() -> task_work_cancel() failed ->
> rcuwait_wait_event().
>
> Once task_work_run() is running, the list of callbacks removed from the
> task_struct and from this point on task_work_cancel() can't remove any
> pending and not yet started work items.

But can this patch really solve the problem?

Suppose we have two tasks, T1 and T2.

T1 does fd = perf_event_open(pid => T2->pid);
T2 does fd = perf_event_open(pid => T1->pid);

Now, both T1 and T2 do close(fd), call task_work_run(), dequeue the
____fput work, and finally call __fput(). Now suppose that both perf
events fire before T1/T2 call perf_event_release_kernel/_free_event.

Now, T1 and T2 will hang forever in perf_pending_task_sync() waiting
for each other. task_work_cancel(current) can't succeed with or without
this patch.

No?

Oleg.