qemu-devel
[Top][All Lists]
Advanced

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

Re: [PATCH v9 3/3] iotests: test nbd reconnect


From: Eric Blake
Subject: Re: [PATCH v9 3/3] iotests: test nbd reconnect
Date: Mon, 7 Oct 2019 15:03:57 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.1.0

On 10/7/19 5:48 AM, Vladimir Sementsov-Ogievskiy wrote:

We want to wait until listening socket is prepared..

In shell:

qemu-nbd --pid-file=/path/to/file ...
while [ ! -e /path/to/file ]; do
    sleep ... # fractional second, or exponential, or whatever...
done
# Now the listening socket is indeed prepared

You'd have to translate that idiom to python.

Don't see, how it is better than what I've done in 04.. But I can resend with 
this.
At least, the fact that socket is initialized before creating pid file is 
undocumented..

I just posted a patch to rectify that.



Or:

pre-open Unix socket at /path/to/socket
LISTEN_PID=... LISTEN_FDS=1 qemu-nbd ... 3<>/path/to/socket

Now the socket is pre-created and passed into qemu-nbd via systemd socket 
activation, so you know the listening socket is ready without having to do any 
loop at all.  Here's a patch in libnbd where we just switched from waiting for 
the port to appear (because the test predated qemu-nbd pidfile support) to 
instead using socket activation, for reference:
https://github.com/libguestfs/libnbd/commit/352331d177


Hmm, I'm afraid I need more help in it, I don't know socket activation and 
googling for some time didn't help.
How to pre-open the socket? How to set LISTEN_PID? Looking at the code I see 
that activation path failed if
LISTEN_PID != getpid().. So I need to know qemu-nbd pid before starting it? o_O


I'm not sure if a shell can open a Unix socket as a server. The shell _does_ have the 'exec' builtin, such that you can manipulate the environment in shell and then use exec to guarantee the qemu-nbd process has the same pid as the shell process that just manipulated the environment; but it doesn't help unless you can also pass in the Unix socket pre-bound, and I'm not aware of command line tools that make that easy (maybe nc can do something like it, but then you have to wonder if nc is adding yet another layer of bounce-buffering). But in other languages (C, Python, ...) you create a Unix socket, call bind() on it, then call fork(). In the parent process, you then close the just-bound fd, and call connect() on the socket - the connect will block until the child process uses the socket, but you are guaranteed that it won't fail because the server side is already bound. In the child process, you use dup2() to move the fd to 3 and clear O_CLOEXEC, manipulate the environment to set LISTEN_PID to the current process id and LISTEN_FDS to 1, then exec. The child process then has the correct id to realize that it has been handed a pre-bound socket, and skips any code that it would normally do to create the socket and bind it.

Note that setting LISTEN_PID in the child process after a fork() from a multi-threaded parent is _extremely_ difficult to do correctly (setenv() is not async-signal-safe, and anything that is not async-signal-safe can cause deadlock if invoked between fork() and exec() if the parent process was multi-threaded) - so it may even be easier to do a double-exec() - the first exec is to a shim to get rid of the async-signal-safe restrictions, and can then set LISTEN_PID without issues, and the second exec to the actual target. But I don't know of any such shim designed for common use.

That said, socket activation isn't a necessity to use, just a convenience. I don't care if the regression test uses socket activation, as long as it works at testing nbd reconnect.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



reply via email to

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