Некоторые системы могут предоставлять execvpe()
.Поиск в Google по запросу «execvpe» показывает множество вариантов, включая, по крайней мере, одну реализацию (значительно более сложную, чем то, что следует, но включает в себя большую часть execvp()
в своем собственном коде).
Для тех, кто это делаетнет, вы можете предоставить это для себя:
int execvpe(const char *program, char **argv, char **envp)
{
char **saved = environ;
int rc;
environ = envp;
rc = execvp(program, argv);
environ = saved;
return rc;
}
Вы, вероятно, могли бы выжить без rc
(просто принудительно возвращая -1), поскольку execvp()
только когда-либо возвращает -1
(и это только когда-либо возвращается наошибка).
Возможно, вам даже не нужно беспокоиться о безопасности потоков в этом коде.Обычный сценарий, который будет использовать его, это сразу после fork()
, и в этот момент в процессе есть только один поток.Если вы думаете, что можете использовать его, когда вокруг несколько потоков, то вам нужно довольно тщательно подумать о том, безопасно ли изменять глобальную среду даже кратко.Ясно, что если execvp()
завершится успешно, проблем не будет (все потоки будут внезапно прерваны).Если произойдет сбой execvp()
, возможно, один из других потоков увидит измененную среду и на основании этого может принять неверные решения.В этом случае вам необходимо надлежащим образом защитить окружающую среду (и это, вероятно, предполагает (взаимное исключение) блокировку в getenv()
, setenv()
и putenv()
, а также в execvpe()
).
(Реализация execvpe()
, которую я обнаружил, позволяет избежать проблем с безопасностью потоков благодаря реализации логики execvp()
и последующему использованию execve()
для выполнения программы.)
Обычно, если execvpe()
возвращается, процесс будетвыход, поэтому очень часто восстановление среды не повлияет на программу.Тем не менее, это лучше, чем потом сожалеть.