Вот правильный способ (или, по крайней мере, один правильный способ) создать асинхронное ожидание из синхронного:
struct waitpid_async_args {
pid_t pid;
int *status;
int flags;
sem_t sem, *done;
int *err;
};
static void *waitpid_async_start(void *arg)
{
struct waitpid_async_args *a = arg;
pid_t pid = a->pid;
int *status = a->status, flags = a->flags, *err = a->err;
sem_post(&a->sem);
if (waitpid(pid, status, flags) < 0) *err = errno;
else *err = 0;
sem_post(a->done);
pthread_detach(pthread_self());
return 0;
}
int waitpid_async(pid_t pid, int *status, int flags, sem_t *done, int *err)
{
struct waitpid_async_args a = { .pid = pid, .status = status,
.flags = flags, .done = done, .err = err };
sigset_t set;
pthread_t th;
int ret;
sem_init(&a.sem, 0, 0);
sigfillset(&set);
pthread_sigmask(SIG_BLOCK, &set, &set);
ret = pthread_create(&th, 0, waidpid_async_start, &a);
if (!ret) sem_wait(&a.sem);
pthread_sigmask(SIG_SETMASK, &set, 0);
return ret;
}
Обратите внимание, что асинхронная функция принимает в качестве дополнительного аргумента семафор, который она отправитчтобы отметить, что это сделано.Вы можете просто проверить status
, но без объекта синхронизации нет формальной гарантии упорядочения памяти, поэтому лучше использовать такой подход и вызывать sem_trywait
или sem_timedwait
с таймаутом, чтобы проверить, доступно ли еще состояниепрежде чем получить к нему доступ.