Jens, I'll read this version tomorrow, but: On 10/01, Jens Axboe wrote: > > static inline int signal_pending(struct task_struct *p) > { > - return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING)); > +#ifdef TIF_TASKWORK > + /* > + * TIF_TASKWORK isn't really a signal, but it requires the same > + * behavior of restarting the system call to force a kernel/user > + * transition. > + */ > + return unlikely(test_tsk_thread_flag(p, TIF_SIGPENDING) || > + test_tsk_thread_flag(p, TIF_TASKWORK)); > +#else > + return unlikely(test_tsk_thread_flag(p, TIF_SIGPENDING)); > +#endif This change alone is already very wrong. signal_pending(task) == T means that this task will do get_signal() as soon as it can, and this basically means you can't "divorce" SIGPENDING and TASKWORK. Simple example. Suppose we have a single-threaded task T. Someone does task_work_add(T, TWA_SIGNAL). This makes signal_pending()==T and this is what we need. Now suppose that another task sends a signal to T before T calls task_work_run() and clears TIF_TASKWORK. In this case SIGPENDING won't be set because signal_pending() is already set (see wants_signal), and this means that T won't notice this signal. Oleg.