Вот способ подождать, пока любой процесс (не обязательно дочерний) в linux завершится (или погибнет) без опроса:
Использование inotify для ожидания удаления / proc'pid было бы идеальным решением, но, к сожалению, inotify не работает с псевдофайловыми системами, такими как / proc.
Однако мы можем использовать его с исполняемым файлом процесса.
Пока этот процесс существует, этот файл остается открытым.
Таким образом, мы можем использовать inotify с IN_CLOSE_NOWRITE для блокировки до тех пор, пока файл не будет закрыт.
Конечно, его можно закрыть по другим причинам (например, если другой процесс с тем же исполняемым файлом завершается), поэтому мы должны отфильтровать эти события другими способами.
Мы можем использовать kill (pid, 0), но это не может гарантировать, что это все тот же процесс. Если мы действительно параноики по этому поводу, мы можем сделать что-то еще.
Вот способ, который должен быть на 100% безопасен от повторного использования pid: мы открываем псевдо-каталог / proc / 'pid' и сохраняем его открытым, пока мы не закончим. Если тем временем создается новый процесс с тем же идентификатором pid, дескриптор файла каталога, который мы храним, все равно будет ссылаться на исходный (или станет недействительным, если старый процесс прекратит существовать), но НИКОГДА не будет ссылаться на новый процесс с повторно использованный пид. Затем мы можем проверить, существует ли исходный процесс, проверяя, например, существует ли файл «cmdline» в каталоге с помощью openat (). Когда процесс завершается или уничтожается, эти псевдофайлы также перестают существовать, поэтому openat () завершится с ошибкой.
вот пример кода:
// return -1 on error, or 0 if everything went well
int wait_for_pid(int pid)
{
char path[32];
int in_fd = inotify_init();
sprintf(path, "/proc/%i/exe", pid);
if (inotify_add_watch(in_fd, path, IN_CLOSE_NOWRITE) < 0) {
close(in_fd);
return -1;
}
sprintf(path, "/proc/%i", pid);
int dir_fd = open(path, 0);
if (dir_fd < 0) {
close(in_fd);
return -1;
}
int res = 0;
while (1) {
struct inotify_event event;
if (read(in_fd, &event, sizeof(event)) < 0) {
res = -1;
break;
}
int f = openat(dir_fd, "fd", 0);
if (f < 0) break;
close(f);
}
close(dir_fd);
close(in_fd);
return res;
}