Вы правы, там есть состояние гонки.Я предлагаю вам заблокировать доставку SIGCHLD
с помощью функции sigprocmask
.Когда вы добавите новый PID в свою структуру данных, снова разблокируйте сигнал.Когда сигнал заблокирован, если этот сигнал получен, ядро запоминает, что ему нужно доставить этот сигнал, а когда сигнал разблокирован, он доставляется.
Вот что я имею в виду, в частности:
sigset_t mask, prevmask;
//Initialize mask with just the SIGCHLD signal
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &mask, &prevmask); /*block SIGCHLD, get previous mask*/
pid = fork();
if(pid == -1)
{
printf("error: fork()\n");
}
else if(pid == 0)
{
execvp(*args, args);
exit(0);
}
else
{
// add process to tracking array
addBGroundProcess(pid, args[0]);
// Unblock SIGCHLD again
sigprocmask(SIG_SETMASK, &prevmask, NULL);
}
Кроме того, я думаю, что есть вероятность, что execvp
может потерпеть неудачу.(В общем, хорошо с этим справиться, даже если в этом случае этого не происходит.) Это зависит от того, как именно это реализовано, но я не думаю, что вам разрешено ставить &
в конце команды, чтобызаставить его работать в фоновом режиме.В любом случае, выполнение emacs
само по себе, вероятно, то, что вам нужно в этом случае, а добавление &
в конец командной строки - это функция, предоставляемая оболочкой.
Редактировать: я видел ваши комментарии о том, как вы не хотите, чтобы emacs работал в текущем терминальном сеансе.Как вы хотите, чтобы он работал, в точности - возможно, в отдельном окне X11?Если это так, есть и другие способы достижения этого.
Довольно простой способ справиться с ошибкой execvp
- сделать это:
execvp(*args, args);
perror("execvp failed");
_exit(127);