On 06/06/22(Mon) 06:47, David Gwynne wrote:
> On Sun, Jun 05, 2022 at 03:57:39PM +0000, Visa Hankala wrote:
> > On Sun, Jun 05, 2022 at 12:27:32PM +0200, Martin Pieuchot wrote:
> > > On 05/06/22(Sun) 05:20, Visa Hankala wrote:
> > > > Encountered the following panic:
> > > > 
> > > > panic: kernel diagnostic assertion "(p->p_flag & P_TIMEOUT) == 0" 
> > > > failed: file "/usr/src/sys/kern/kern_synch.c", line 373
> > > > Stopped at      db_enter+0x10:  popq    %rbp
> > > >     TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
> > > >  423109  57118     55         0x3          0    2  link
> > > >  330695  30276     55         0x3          0    3  link
> > > > * 46366  85501     55      0x1003  0x4080400    1  link
> > > >  188803  85501     55      0x1003  0x4082000    0K link
> > > > db_enter() at db_enter+0x10
> > > > panic(ffffffff81f25d2b) at panic+0xbf
> > > > __assert(ffffffff81f9a186,ffffffff81f372c8,175,ffffffff81f87c6c) at 
> > > > __assert+0x25
> > > > sleep_setup(ffff800022d64bf8,ffff800022d64c98,20,ffffffff81f66ac6,0) at 
> > > > sleep_setup+0x1d8
> > > > cond_wait(ffff800022d64c98,ffffffff81f66ac6) at cond_wait+0x46
> > > > timeout_barrier(ffff8000228a28b0) at timeout_barrier+0x109
> > > > timeout_del_barrier(ffff8000228a28b0) at timeout_del_barrier+0xa2
> > > > sleep_finish(ffff800022d64d90,1) at sleep_finish+0x16d
> > > > tsleep(ffffffff823a5130,120,ffffffff81f0b730,2) at tsleep+0xb2
> > > > sys_nanosleep(ffff8000228a27f0,ffff800022d64ea0,ffff800022d64ef0) at 
> > > > sys_nanosleep+0x12d
> > > > syscall(ffff800022d64f60) at syscall+0x374
> > > > 
> > > > The panic is a regression of sys/kern/kern_timeout.c r1.84. Previously,
> > > > soft-interrupt-driven timeouts could be deleted synchronously without
> > > > blocking. Now, timeout_del_barrier() can sleep regardless of the type
> > > > of the timeout.
> > > > 
> > > > It looks that with small adjustments timeout_del_barrier() can sleep
> > > > in sleep_finish(). The management of run queues is not affected because
> > > > the timeout clearing happens after it. As timeout_del_barrier() does not
> > > > rely on a timeout or signal catching, there should be no risk of
> > > > unbounded recursion or unwanted signal side effects within the sleep
> > > > machinery. In a way, a sleep with a timeout is higher-level than
> > > > one without.
> > > 
> > > I trust you on the analysis.  However this looks very fragile to me.
> > > 
> > > The use of timeout_del_barrier() which can sleep using the global sleep
> > > queue is worrying me.  
> > 
> > I think the queue handling ends in sleep_finish() when SCHED_LOCK()
> > is released. The timeout clearing is done outside of it.
> 
> That's ok.
> 
> > The extra sleeping point inside sleep_finish() is subtle. It should not
> > matter in typical use. But is it permissible with the API? Also, if
> > timeout_del_barrier() sleeps, the thread's priority can change.
> 
> What other options do we have at this point? Spin? Allocate the timeout
> dynamically so sleep_finish doesn't have to wait for it and let the
> handler clean up? How would you stop the timeout handler waking up the
> thread if it's gone back to sleep again for some other reason?
> 
> Sleeping here is the least worst option.

I agree.  I don't think sleeping is bad here.  My concern is about how
sleeping is implemented.  There's a single API built on top of a single
global data structure which now calls itself recursively.  

I'm not sure how much work it would be to make cond_wait(9) use its own
sleep queue...  This is something independent from this fix though.

> As for timeout_del_barrier, if prio is a worry we can provide an
> advanced version of it that lets you pass the prio in. I'd also
> like to change timeout_barrier so it queues the barrier task at the
> head of the pending lists rather than at the tail.

I doubt prio matter.

Reply via email to