Skip to content

Commit 3d658cc

Browse files
committed
Use a pipe instead of signals to notify readiness
This avoids using async signal unsafe functions in a signal handler. It also reduces the total amount of code.
1 parent f3768d2 commit 3d658cc

File tree

1 file changed

+27
-33
lines changed

1 file changed

+27
-33
lines changed

daemon/qrexec-daemon.c

+27-33
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ static const char *policy_program = QREXEC_POLICY_PROGRAM;
120120
# define UNUSED(x) UNUSED_ ## x
121121
#endif
122122

123-
static volatile int children_count;
124123
static volatile int child_exited;
125124
static volatile int terminate_requested;
126125

@@ -135,24 +134,6 @@ static
135134
#endif
136135
int protocol_version;
137136

138-
static void sigusr1_handler(int UNUSED(x))
139-
{
140-
if (!opt_quiet)
141-
LOG(INFO, "Connected to VM");
142-
exit(0);
143-
}
144-
145-
static void sigchld_parent_handler(int UNUSED(x))
146-
{
147-
children_count--;
148-
/* starting value is 0 so we see dead real qrexec-daemon as -1 */
149-
if (children_count < 0) {
150-
LOG(ERROR, "Connection to the VM failed");
151-
exit(1);
152-
}
153-
}
154-
155-
156137
static char *remote_domain_name; // guess what
157138
static int remote_domain_id;
158139

@@ -308,29 +289,41 @@ static void init(int xid)
308289
startup_timeout = MAX_STARTUP_TIME_DEFAULT;
309290
}
310291

292+
int pipes[2];
311293
if (!opt_direct) {
312-
struct sigaction action = {
313-
.sa_handler = sigusr1_handler,
314-
.sa_flags = 0,
315-
};
316-
if (sigaction(SIGUSR1, &action, NULL))
317-
err(1, "sigaction");
318-
action.sa_handler = sigchld_parent_handler;
319-
if (sigaction(SIGCHLD, &action, NULL))
320-
err(1, "sigaction");
294+
if (pipe2(pipes, O_CLOEXEC))
295+
err(1, "pipe2()");
321296
switch (pid=fork()) {
322297
case -1:
323298
PERROR("fork");
324299
exit(1);
325300
case 0:
301+
close(pipes[0]);
326302
break;
327303
default:
328304
if (getenv("QREXEC_STARTUP_NOWAIT"))
329305
exit(0);
306+
close(pipes[1]);
330307
if (!opt_quiet)
331308
LOG(ERROR, "Waiting for VM's qrexec agent.");
309+
struct pollfd fds[1] = {{ .fd = pipes[0], .events = POLLIN | POLLHUP, .revents = 0 }};
332310
for (i=0;i<startup_timeout;i++) {
333-
sleep(1);
311+
int res = poll(fds, 1, 1000);
312+
if (res < 0)
313+
err(1, "poll()");
314+
if (res) {
315+
char buf[1];
316+
ssize_t bytes = read(pipes[0], buf, sizeof buf);
317+
if (bytes < 0)
318+
err(1, "read()");
319+
if (bytes == 0) {
320+
LOG(ERROR, "Connection to the VM failed");
321+
exit(1);
322+
}
323+
if (!opt_quiet)
324+
LOG(INFO, "Connected to VM");
325+
exit(0);
326+
}
334327
if (!opt_quiet)
335328
fprintf(stderr, ".");
336329
if (i==startup_timeout-1) {
@@ -419,12 +412,13 @@ static void init(int xid)
419412
err(1, "signal");
420413
if (sigaction(SIGCHLD, &sigchld_action, NULL))
421414
err(1, "sigaction");
422-
if (signal(SIGUSR1, SIG_DFL) == SIG_ERR)
423-
err(1, "signal");
424415
if (sigaction(SIGTERM, &sigterm_action, NULL))
425416
err(1, "sigaction");
426-
if (!opt_direct)
427-
kill(getppid(), SIGUSR1); // let the parent know we are ready
417+
if (!opt_direct) {
418+
if (write(pipes[1], "", 1) != 1)
419+
err(1, "write(pipe)");
420+
close(pipes[1]);
421+
}
428422
}
429423

430424
static int send_client_hello(int fd)

0 commit comments

Comments
 (0)