Date: Wed, 14 Dec 2016 12:11:46 +0000 From: Ian Campbell <ian.campbell@docker.com> To: Peter Grehan <grehan@freebsd.org> Cc: Tycho Nightingale <tychon@freebsd.org>, freebsd-virtualization@freebsd.org, Anil Madhavapeddy <anil@recoil.org> Subject: Re: Query about bhyve's blockif_cancel and the signalling mechanisms Message-ID: <CAOc2ZU1u29c4oY8Q8BcWrTp15qftZLONuXqYsaOXNq01FuExFw@mail.gmail.com> In-Reply-To: <631f775d-8d61-55ba-1e7b-8ce4fcadcbf3@freebsd.org> References: <CAOc2ZU0Hqvctv767ESu6fKwXJ3W35ReqM3=ud6G3MzKLSEY=Bw@mail.gmail.com> <631f775d-8d61-55ba-1e7b-8ce4fcadcbf3@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On 13 December 2016 at 06:32, Peter Grehan <grehan@freebsd.org> wrote: >> I've dug around in the FreeBSD kevent and signal man pages but I >> cannot find any part which describes anything of the semantics which >> bhyve seems to be relying on (which seems to be that the system call >> in the target thread will return EINTR at some point before the thread >> which is "handling" the signal via kevent/kqueue sees that event). >> >> Have I missed something here or is bhyve relying on some subtle >> underlying semantics? > > > I didn't think it too FreeBSD-specific - if a thread is blocked in a system > call, sending a signal should force it to exit on most Unices. Sure, the thing I was unsure about was whether that was the case when the application has asked for signal delivery via some other mechanism than the traditional asynchronous signal handlers such as kevent. Especially when the signal itself if SIG_IGN'd (as SIGCONT is in bhyve in blockif_init). The attached test tries to mimic what bhyve is doing, it has a blocked io thread and a thread handling kevents, with the signal set to SIG_IGN. A signal is then sent to the io thread. Running it on FreeBSD 11[0] it outputs: main: starting kevent thread main: starting io thread kevent thread: opening kqueue kevent thread: setting up SIGCONT event kevent thread: waiting for SIGCONT event io thread: blocking in read main: sending SIGCONT io thread main: waiting for io thread to complete kevent thread: received SIGCONT event and then blocks indefinitely. The kevent thread has seen the SIGCONT but the read in the io thread has not been interrupted. If I #define USE_HANDLER at the same time as USE_KEVENT then instead I see: main: starting kevent thread kevent thread: opening kqueue main: starting io thread kevent thread: setting up SIGCONT event io thread: blocking in read kevent thread: waiting for SIGCONT event main: sending SIGCONT io thread sigcont: received SIGCONT main: waiting for io thread to complete io thread: Read from pipe returned errno=4: Interrupted system call io thread: exiting main: waiting for kevent thread to complete kevent thread: received SIGCONT event main: all done i.e. the signal is seen by both the kevent thread and the async handler in the io thread, the latter of which causes EINTR from the read. bhyve sets SIGCONT to SIG_IGN so falls into the first case I think. If there is really a bhyve bug here I think it should be fixable with a dummy SIGCONT handler alongside the kevent thread. I think it wouldn't be reliant on a specific ordering of kevent vs async handler invocation due to the while loop on status == BUSY in blockif_cancel which Tycho opened my eyes to earlier. Ian. [0] ftp://ftp.freebsd.org/pub/FreeBSD/releases/VM-IMAGES/11.0-RELEASE/amd64/Latest/FreeBSD-11.0-RELEASE-amd64.qcow2.xz fed to virt-manager.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAOc2ZU1u29c4oY8Q8BcWrTp15qftZLONuXqYsaOXNq01FuExFw>