slirp: simplify fork_exec()

Use g_spawn_async_with_fds() to setup the child.

GSpawn handles reaping the child, and closing parent file descriptors.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
This commit is contained in:
Marc-André Lureau 2018-11-14 16:36:05 +04:00 committed by Samuel Thibault
parent 0aeb4f2c94
commit 2bdb920ece

View File

@ -129,56 +129,53 @@ err:
return -1; return -1;
} }
static void
fork_exec_child_setup(gpointer data)
{
setsid();
}
int int
fork_exec(struct socket *so, const char *ex) fork_exec(struct socket *so, const char *ex)
{ {
char **argv; GError *err = NULL;
int opt, c, sp[2]; char **argv;
pid_t pid; int opt, sp[2];
DEBUG_CALL("fork_exec"); DEBUG_CALL("fork_exec");
DEBUG_ARG("so = %p", so); DEBUG_ARG("so = %p", so);
DEBUG_ARG("ex = %p", ex); DEBUG_ARG("ex = %p", ex);
if (slirp_socketpair_with_oob(sp) < 0) { if (slirp_socketpair_with_oob(sp) < 0) {
return 0; return 0;
} }
pid = fork(); argv = g_strsplit(ex, " ", -1);
switch(pid) { g_spawn_async_with_fds(NULL /* cwd */,
case -1: argv,
error_report("Error: fork failed: %s", strerror(errno)); NULL /* env */,
closesocket(sp[0]); G_SPAWN_SEARCH_PATH,
closesocket(sp[1]); fork_exec_child_setup, NULL /* data */,
return 0; NULL /* child_pid */,
sp[1], sp[1], sp[1],
&err);
g_strfreev(argv);
case 0: if (err) {
setsid(); error_report("%s", err->message);
dup2(sp[1], 0); g_error_free(err);
dup2(sp[1], 1); closesocket(sp[0]);
dup2(sp[1], 2); closesocket(sp[1]);
for (c = getdtablesize() - 1; c >= 3; c--) return 0;
close(c); }
argv = g_strsplit(ex, " ", -1); so->s = sp[0];
execvp(argv[0], (char **)argv); closesocket(sp[1]);
socket_set_fast_reuse(so->s);
/* Ooops, failed, let's tell the user why */ opt = 1;
fprintf(stderr, "Error: execvp of %s failed: %s\n", qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
argv[0], strerror(errno)); qemu_set_nonblock(so->s);
close(0); close(1); close(2); /* XXX */ return 1;
exit(1);
default:
so->s = sp[0];
closesocket(sp[1]);
qemu_add_child_watch(pid);
socket_set_fast_reuse(so->s);
opt = 1;
qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
qemu_set_nonblock(so->s);
return 1;
}
} }
#endif #endif