slave: user-notifications: don't block in write(3)

The main process is blocking and waiting for us to close the error
pipe (in exec(3), via O_CLOEXEC).

Thus, pts data will *not* be processed until we've exec:d the shell.

Because of this we must not write too much and block in write(3). Do
this by setting O_NONBLOCK on the pts fd (*after* dup:ing it to
stdin/stderr/sdout) and watch for EAGAIN EWOULDBLOCK.
This commit is contained in:
Daniel Eklöf 2020-07-31 17:15:51 +02:00
parent b661513245
commit a7d21c5c7f
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

18
slave.c
View file

@ -93,6 +93,16 @@ emit_one_notification(int fd, const struct user_notification *notif)
write(fd, notif->text, strlen(notif->text)) < 0 ||
write(fd, postfix, strlen(postfix)) < 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN) {
/*
* The main process is blocking and waiting for us to
* close the error pipe. Thus, pts data will *not* be
* processed until we've exec:d. This means we cannot
* write anymore once the kernel buffer is full. Don't
* treat this as a fatal error.
*/
return true;
}
return false;
}
@ -186,6 +196,14 @@ slave_exec(int ptmx, char *argv[], int err_fd, bool login_shell,
goto err;
}
{
int flags = fcntl(pts, F_GETFL);
if (flags < 0)
goto err;
if (fcntl(pts, F_SETFL, flags | O_NONBLOCK) < 0)
goto err;
}
if (!emit_notifications(pts, notifications))
goto err;