Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Функция может быть прервана сигналом, таким образом, Вы могли установить таймер прежде, чем назвать waitpid (), и это выйдет с EINTR, когда сигнал таймера будет повышен.Править: Это должно быть столь же просто как называющий предупреждение (5) прежде, чем назвать waitpid ().
Не смешивайтесь alarm()
с wait()
. Можно потерять информацию об ошибке тот путь.
Использование прием самоканала. Это превращает любой сигнал в select()
способное событие:
int selfpipe[2];
void selfpipe_sigh(int n)
{
int save_errno = errno;
(void)write(selfpipe[1], "",1);
errno = save_errno;
}
void selfpipe_setup(void)
{
static struct sigaction act;
if (pipe(selfpipe) == -1) { abort(); }
fcntl(selfpipe[0],F_SETFL,fcntl(selfpipe[0],F_GETFL)|O_NONBLOCK);
fcntl(selfpipe[1],F_SETFL,fcntl(selfpipe[1],F_GETFL)|O_NONBLOCK);
memset(&act, 0, sizeof(act));
act.sa_handler = selfpipe_sigh;
sigaction(SIGCHLD, &act, NULL);
}
Затем Ваша подобная waitpid функция похожа на это:
int selfpipe_waitpid(void)
{
static char dummy[4096];
fd_set rfds;
struct timeval tv;
int died = 0, st;
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(selfpipe[0], &rfds);
if (select(selfpipe[0]+1, &rfds, NULL, NULL, &tv) > 0) {
while (read(selfpipe[0],dummy,sizeof(dummy)) > 0);
while (waitpid(-1, &st, WNOHANG) != -1) died++;
}
return died;
}
Вы видите в selfpipe_waitpid()
, как можно управлять тайм-аутом и даже смешаться с другим select()
- основывал IO.
Если Вы собираетесь использовать сигналы так или иначе (согласно предложению Steve), можно просто отправить сигнал вручную, когда Вы хотите выйти. Это заставит waitpid возвращать EINTR, и поток может тогда выйти. Никакая потребность в периодическом предупреждении/перезапуске.
я могу использовать обработчик сигналов для SIGCHLD, и в обработчике сигналов делают то, что я собирался сделать, когда ребенок выходит, или отправьте сообщение в различный поток, чтобы сделать некоторое действие. Но использование обработчика сигналов запутывает поток кода немного.
для предотвращения условий состязания, необходимо постараться не делать что-либо более сложное, чем изменение энергозависимого флага в обработчике сигналов.
я думаю, что наилучший вариант в Вашем случае состоит в том, чтобы отправить сигнал в родителя. waitpid () тогда установит errno на EINTR и возврат. В этой точке Вы проверяете на waitpid возвращаемое значение и errno, замечаете, что были отправлены сигнал и принимаете соответствующие меры.