qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] linux-user: interrupting syscalls


From: Peter Maydell
Subject: Re: [Qemu-devel] linux-user: interrupting syscalls
Date: Fri, 17 Jan 2014 16:40:13 +0000

This is resurrecting a two year old waffly proposal (full text
here: http://lists.gnu.org/archive/html/qemu-devel/2011-12/msg00384.html)
because I realised my idea was broken.

On 4 December 2011 16:29, Peter Maydell <address@hidden> wrote:
> When run natively, this program will block until you send it a
> SIGUSR1; the signal handler will write to the pipe and cause the read
> to complete. Run in linux-user mode, we deadlock, because qemu does
> not run the guest signal handler when in the middle of emulating a
> system call -- it merely queues it to be run when the syscall
> finishes. For cases like this where the event that causes the syscall
> to complete is actually triggered by the guest signal handler, this
> doesn't work.  (There is a real-world instance of this problem in the
> Boehm garbage collector, where a signal handler posts to a semaphore
> which is being waited on by the mainline code.)
>
> It's not sufficient to simply force all syscalls to be non-restartable
> (and then to take the signal when the syscall returns EINTR), because
> of the following race condition:
>  * qemu enters do_syscall on behalf of main thread
>  * do_syscall is about to call the underlying syscall, when...
>  * the signal arrives (and we queue it)
>  * do_syscall then calls the host syscall, which will block. Oops.
>
> To fix this I think we need to have linux-user's signal handler
> wrapper do a siglongjmp if a signal arrives while we're inside
> do_syscall(). This allows us to properly interrupt whether we'd
> got to the point of making the host syscall or not.

This won't work, because there's no way to tell the difference
between "we longjmped out of a write syscall before the kernel
wrote anything" and "we longjmped out just after the kernel
returned from a write syscall having written the buffer", so
you can't tell if you need to repeat the syscall or not.

I'm no longer sure if there's any fix for these races at all :-(

thanks
-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]