On Wed, Oct 17, 2018 at 11:06:43AM +0200, Michal Privoznik wrote: > This new helper can be used to spawn a child process and run > passed callback from it. This will come handy esp. if the > callback is not thread safe. > > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > src/libvirt_private.syms | 1 + > src/util/virprocess.c | 81 ++++++++++++++++++++++++++++++++++++++++ > src/util/virprocess.h | 16 ++++++++ > 3 files changed, 98 insertions(+) > +/** > + * virProcessRunInFork: > + * @cb: callback to run > + * @opaque: opaque data to @cb > + * > + * Do the fork and run @cb in the child. This can be used when > + * @cb does something thread unsafe, for instance. However, due > + * to possible signal propagation @cb should only call async > + * signal safe functions. On return, the returned value is either > + * -1 with error message reported if something went bad in the > + * parent, if child has died from a signal or if the child > + * returned EXIT_CANCELED. Otherwise the returned value is the > + * exit status of the child. Instead of; However, due to possible signal propagation @cb should only call async signal safe functions. Use: All signals will be reset to have their platform default handlers and unmasked. @cb must only use async signal safe functions. In particular no mutexes should be used in @cb, unless steps were taken before forking to guarantee a predictable state. @cb must not exec any external binaries, instead virCommand/virExec should be used for that purpose. > + */ > +int > +virProcessRunInFork(virProcessForkCallback cb, > + void *opaque) > +{ > + int ret = -1; > + pid_t child = -1; > + pid_t parent = getpid(); > + int errfd[2] = { -1, -1 }; > + > + if (pipe2(errfd, O_CLOEXEC) < 0) { > + virReportSystemError(errno, "%s", > + _("Cannot create pipe for child")); > + return -1; > + } > + > + if ((child = virFork()) < 0) > + goto cleanup; > + > + if (child == 0) { > + VIR_FORCE_CLOSE(errfd[0]); > + ret = virProcessForkHelper(errfd[1], parent, cb, opaque); > + VIR_FORCE_CLOSE(errfd[1]); > + _exit(ret < 0 ? EXIT_CANCELED : ret); > + } else { > + int status; > + VIR_AUTOFREE(char *) buf = NULL; > + > + VIR_FORCE_CLOSE(errfd[1]); > + ignore_value(virFileReadHeaderFD(errfd[0], 1024, &buf)); > + ret = virProcessWait(child, &status, false); > + if (!ret) { > + ret = status == EXIT_CANCELED ? -1 : status; > + if (ret) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("child reported: %s"), > + NULLSTR(buf)); It would be desirable to include the exit status value in the message > + } > + } > + } > + > + cleanup: > + VIR_FORCE_CLOSE(errfd[0]); > + VIR_FORCE_CLOSE(errfd[1]); > + return ret; > +} 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list