From: "Daniel P. Berrangé" <berrange@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: qemu-devel@nongnu.org, airlied@redhat.com, kraxel@redhat.com
Subject: Re: [Qemu-devel] [PATCH v4 20/29] util: add qemu_write_pidfile()
Date: Fri, 31 Aug 2018 11:42:58 +0100 [thread overview]
Message-ID: <20180831104258.GA5088@redhat.com> (raw)
In-Reply-To: <20180713130916.4153-21-marcandre.lureau@redhat.com>
On Fri, Jul 13, 2018 at 03:09:07PM +0200, Marc-André Lureau wrote:
> There are variants of qemu_create_pidfile() in qemu-pr-helper and
> qemu-ga. Let's have a common implementation in libqemuutil.
>
> The code is based from pr-helper write_pidfile(), but allows the
> caller to deal with error reporting and behaviour.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> diff --git a/util/oslib-posix.c b/util/oslib-posix.c
> index 13b6f8d776..da1d4a3201 100644
> --- a/util/oslib-posix.c
> +++ b/util/oslib-posix.c
> @@ -88,6 +88,39 @@ int qemu_daemon(int nochdir, int noclose)
> return daemon(nochdir, noclose);
> }
>
> +bool qemu_write_pidfile(const char *pidfile, Error **errp)
> +{
> + int pidfd;
> + char pidstr[32];
> +
> + pidfd = qemu_open(pidfile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
> + if (pidfd == -1) {
> + error_setg_errno(errp, errno, "Cannot open pid file");
> + return false;
> + }
> +
> + if (lockf(pidfd, F_TLOCK, 0)) {
> + error_setg_errno(errp, errno, "Cannot lock pid file");
> + goto fail;
> + }
> + if (ftruncate(pidfd, 0)) {
> + error_setg_errno(errp, errno, "Failed to truncate pid file");
> + goto fail;
> + }
> +
> + snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
> + if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
> + error_setg(errp, "Failed to write pid file");
> + goto fail;
> + }
> + return true;
> +
> +fail:
> + unlink(pidfile);
> + close(pidfd);
> + return false;
> +}
Thinking about this again, I think it is not robust enough.
QEMU will leave the pidfile existing on disk when it exits which
initially made me think it avoids the deletion race. The app
managing QEMU, however, may well delete the pidfile after it has
seen QEMU exit, and even if the app locks the pidfile before
deleting it, there is still a race.
eg consider the following sequence
QEMU 1 libvirtd QEMU 2
1. lock(pidfile)
2. exit()
3. open(pidfile)
4. lock(pidfile)
5. open(pidfile)
6. unlink(pidfile)
7. close(pidfile)
8. lock(pidfile)
IOW, at step 8 the new QEMU has successfully acquired the lock, but the
pidfile no longer exists on disk because it was deleted after the original
QEMU exited.
While we could just say no external app should ever delete the pidfile,
I don't think that is satisfactory as people don't read docs, and admins
don't like stale pidfiles being left around on disk.
To make this robust, I think we might want to copy libvirt's approach to
pidfile acquisition which runs in a loop and checks that the file on
disk /after/ acquiring the lock matches the file that was locked. Then
we could in fact safely let QEMU delete its own pidfiles on clean exit.
while (1) {
struct stat a, b;
if ((fd = open(path, O_WRONLY|O_CREAT, 0644)) < 0) {
return -1;
}
if (fstat(fd, &b) < 0) {
close(fd);
return -1;
}
if (lockf(fd, F_TLOCK, 0) < 0) {
close(fd);
return -1;
}
/* Now make sure the pidfile we locked is the same
* one that now exists on the filesystem
*/
if (stat(path, &a) < 0) {
close(fd);
/* Someone else must be racing with us, so try again */
continue;
}
if (a.st_ino == b.st_ino)
break;
close(fd);
/* Someone else must be racing with us, so try again */
}
if (ftruncate(fd, 0)) {
close(fd);
return -1;
}
snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
close(fd);
return -1;
}
return fd;
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2018-08-31 10:43 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-13 13:08 [Qemu-devel] [PATCH v4 00/29] vhost-user for input & GPU Marc-André Lureau
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 01/29] chardev: avoid crash if no associated address Marc-André Lureau
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 02/29] chardev: remove qemu_chr_fe_read_all() counter Marc-André Lureau
2018-08-28 15:05 ` Daniel P. Berrangé
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 03/29] chardev: unref if underlying chardev has no parent Marc-André Lureau
2018-08-28 15:06 ` Daniel P. Berrangé
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 04/29] dmabuf: add y0_top, pass it to spice Marc-André Lureau
2018-08-21 6:25 ` Gerd Hoffmann
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 05/29] vhost-user: simplify vhost_user_init/vhost_user_cleanup Marc-André Lureau
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 06/29] libvhost-user: exit by default on VHOST_USER_NONE Marc-André Lureau
2018-08-28 13:12 ` Jens Freimann
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 07/29] vhost-user: wrap some read/write with retry handling Marc-André Lureau
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 08/29] Add vhost-user-backend Marc-André Lureau
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 09/29] qio: add qio_channel_command_new_spawn_with_pre_exec() Marc-André Lureau
2018-08-28 15:09 ` Daniel P. Berrangé
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 10/29] HACK: vhost-user-backend: allow to specify binary to execute Marc-André Lureau
2018-08-28 15:44 ` Daniel P. Berrangé
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 11/29] vhost-user: split vhost_user_read() Marc-André Lureau
2018-08-28 15:46 ` Daniel P. Berrangé
2018-07-13 13:08 ` [Qemu-devel] [PATCH v4 12/29] vhost-user: add vhost_user_input_get_config() Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 13/29] libvhost-user: export vug_source_new() Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 14/29] contrib: add vhost-user-input Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 15/29] Add vhost-user-input-pci Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 16/29] vhost-user: add vhost_user_gpu_set_socket() Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 17/29] vhost-user: add vhost_user_gpu_get_num_capsets() Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 18/29] virtio: add virtio-gpu bswap helpers header Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 19/29] util: promote qemu_egl_rendernode_open() to libqemuutil Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 20/29] util: add qemu_write_pidfile() Marc-André Lureau
2018-08-28 15:52 ` Daniel P. Berrangé
2018-08-28 16:04 ` Marc-André Lureau
2018-08-31 10:42 ` Daniel P. Berrangé [this message]
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 21/29] util: use fcntl() for qemu_write_pidfile() locking Marc-André Lureau
2018-08-28 15:59 ` Daniel P. Berrangé
2018-08-28 16:07 ` Marc-André Lureau
2018-08-28 23:41 ` Marc-André Lureau
2018-08-29 8:12 ` Daniel P. Berrangé
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 22/29] contrib: add vhost-user-gpu Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 23/29] virtio-gpu: remove unused qdev Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 24/29] virtio-gpu: remove unused config_size Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 25/29] virtio-gpu: block both 2d and 3d rendering Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 26/29] virtio-gpu: remove useless 'waiting' field Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 27/29] virtio-gpu: split virtio-gpu, introduce virtio-gpu-base Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 28/29] virtio-gpu: split virtio-gpu-pci & virtio-vga Marc-André Lureau
2018-07-13 13:09 ` [Qemu-devel] [PATCH v4 29/29] hw/display: add vhost-user-vga & gpu-pci Marc-André Lureau
2018-08-29 9:13 ` Daniel P. Berrangé
2018-08-14 23:26 ` [Qemu-devel] [PATCH v4 00/29] vhost-user for input & GPU Marc-André Lureau
2018-08-21 7:51 ` Gerd Hoffmann
2018-08-21 10:10 ` Marc-André Lureau
2018-08-21 10:13 ` Daniel P. Berrangé
2018-08-28 10:49 ` Marc-André Lureau
2018-08-29 9:50 ` Daniel P. Berrangé
2018-08-29 10:22 ` Dr. David Alan Gilbert
2018-08-29 10:37 ` Daniel P. Berrangé
2018-08-29 11:34 ` Marc-André Lureau
2018-09-07 13:11 ` Marc-André Lureau
2018-09-11 8:59 ` Gerd Hoffmann
2018-09-11 9:16 ` Marc-André Lureau
2018-09-11 10:44 ` Gerd Hoffmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180831104258.GA5088@redhat.com \
--to=berrange@redhat.com \
--cc=airlied@redhat.com \
--cc=kraxel@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.