Allow concurrent child processes

When multiple child processes are running, closing the
stdin of one child did not send EOF or cause POLLNVAL,
as long as a dup()'ed filedes still existed.

This fixes an issue when running an mp3 encoder while the
video monitor is visible, and will allow to concurrently
run multiple mp3 encoders or other child processes.

Previously this caused Ardour to hang indefinitely in CmdPipeWriter
```
 _proc->close_stdin();
 _proc->wait(); // << here
```
This commit is contained in:
Robin Gareus 2023-03-25 06:09:43 +01:00
parent 70df054d68
commit 3715154a8e
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 36 additions and 2 deletions

View File

@ -920,6 +920,7 @@ SystemExec::close_stdin()
if (pin[1] < 0) {
return;
}
fsync (pin[1]);
close_fd (pin[0]);
close_fd (pin[1]);
fsync (pout[0]);

View File

@ -21,6 +21,9 @@
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
@ -35,6 +38,32 @@
extern char **environ;
static void close_fd (int *fd) { if ((*fd) >= 0) close (*fd); *fd = -1; }
static int close_allv (const int except_fds[]) {
struct rlimit rl;
if (getrlimit (RLIMIT_NOFILE, &rl) < 0) {
return -1;
}
for (int fd = 0; fd < (int) rl.rlim_max; fd++) {
if (fd <= 3) {
continue;
}
for (int i = 0; except_fds[i] >= 0; i++) {
if (except_fds[i] == fd) {
continue;
}
}
if (close (fd) < 0 && errno != EBADF) {
return -1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
if (argc < 10) {
// TODO: if argv > 3, assume pok[] is given, notifify parent.
@ -53,6 +82,8 @@ int main(int argc, char *argv[]) {
pout[0] = atoi(argv[5]);
pout[1] = atoi(argv[6]);
int good_fds[3] = { pok[1], pout[1], -1 };
int stderr_mode = atoi(argv[7]);
int nicelevel = atoi(argv[8]);
@ -106,8 +137,10 @@ int main(int argc, char *argv[]) {
signal(SIGPIPE, SIG_DFL);
#endif
/* all systems go */
execve(argv[9], &argv[9], envp);
if (0 == close_allv (good_fds)) {
/* all systems go */
execve(argv[9], &argv[9], envp);
}
/* if we reach here something went wrong.. */
char buf = 0;