2012-06-26 5 views
1

Давайте предположим, что у нас есть код делает что-то вроде этого:Что делать, если exec() не работает?

int pipes[2]; 
pipe(pipes); 
pid_t p = fork(); 
if(0 == p) 
{ 
    dup2(pipes[1], STDOUT_FILENO); 
    execv("/path/to/my/program", NULL); 
    ... 
} 
else 
{ 
//... parent process stuff 
} 

Как вы можете видеть, это создает трубу, разветвление и использовать трубу для чтения вывода ребенка (я не могу использовать popen здесь, потому что Мне также нужен PID дочернего процесса для других целей).

Вопрос в том, что должно произойти, если в приведенном выше коде execv не удается? Должен ли я вызвать exit() или abort()? Насколько я знаю, эти функции закрывают дескрипторы открытых файлов. Поскольку процесс fork -ed наследует дескрипторы файла родителя, означает ли это, что дескрипторы файла, используемые родительским процессом, станут непригодными?

UPD

Я хочу подчеркнуть, что речь идет не о исполняемом нагруженной Exec() не удается, но сам EXEC, например, в случае, если файл, указанный первым аргументом, не найден или не является исполняемым.

+0

Если вы не хотите путать поток управления, я бы рекомендовал exit() с известным кодом выхода на неудавшемся exec. – Petesh

+0

Эй, ребята, но что, если 'exit()' тоже не удается? –

+0

Я не думаю, что это должно быть проблемой: любые забавные вещи, которые происходят в функциях atexit, приведут к ненормальному завершению в худшем случае, иначе мы не будем контролировать его (выход никогда не возвращается). –

ответ

3

Вы должны использовать exit(int), поскольку (младший байт) аргумента может быть прочитан родительским процессом с использованием waitpid(). Это позволяет обрабатывать ошибку соответствующим образом в родительском процессе. В зависимости от вашей программы вы можете использовать _exit вместо exit. Разница в том, что _exit не будет запускать функции, зарегистрированные с помощью atexit, и не будет потопить потоки stdio.

+0

+1 Больше, чем мой ответ. – Duck

0

Существует около десятка причин, по которым может возникнуть ошибка execv(), и вы можете обращаться с ними по-разному.

Несовершенство ребенка не повлияет на дескрипторы файла родителя. Они, по сути, подсчитываются.

0

Необходимо позвонить по номеру _exit(). Он делает все, что делает exit(), но избегает вызова каких-либо зарегистрированных функций atexit(). Вызов _exit() означает, что родительский элемент сможет получить статус выхода из отказа вашего ребенка и предпринять необходимые шаги.

Смежные вопросы