LINUX.ORG.RU

posix_spawn, Обнаружение ошибки загрузки процесса


0

0

Народ, такая проблема, юзаю posix_spawn для загрузки процесса, в доке написано что эта функция не всегда корректно возвращает ошибку, т.е если я дал ей имя файла, который на самом деле не является исполняемым, то posix_spawn всё-равно скажет что всё в порядке, а затем надо вызвать waitpid или wait и при помощи макроса WIFEXITED узнать, произошла ли ошибка при запуске нового процесса. Проблема только в том что wait/waitpid блокирует исполнение текущей программы. Т.е если я передал в posix_spawn левый файл, то waitpid быстро вернётся и скажет что ошибка, а если передать нормальный образ, то waitpid будет ждать до бесконечности(ну, пока новый процесс не изменит своего состояния, а он этого не сделает, т.к поднялся и работает нормально). Если же в опции waitpid передать WNOHANG, то WIFEXITED всегда возвращает false =( Подскажите что делать, как ждать до тех пор, пока процесс либо проинициализируется либо скажет, что он не может подняться, т.е переданный образ не корректный ?

P.S: Про posix_spawn можно прочитать так: man 3p posix_spawn


по моемому ты чегото недопонимаеш в работе WAITPID().

а мож тебе нужны wait3() OR wait4()?

cvv ★★★★★
()
Ответ на: комментарий от cvv

Почему же, понимаю, эта функция блокирует(если не укзано иначе в options) вызывающий процесс и ждёт пока процесс с идентификатором pid не изменит своего состояния, ну т.е либо получит сигнал, либо выйдет, либо неудачный запуск (status = 127). А чем wait3 и wait4 лучше ? Как они мне помогут решить проблему ?

Мне нужно сразу после posix_spawn ждать до тех пор пока я точно не узнаю поднялся ли процесс окончательно либо ему подняться не удалось.

Sheph
() автор топика

> Народ, такая проблема, юзаю posix_spawn для загрузки процесса, в доке написано что эта функция не всегда корректно возвращает ошибку, т.е если я дал ей имя файла, который на самом деле не является исполняемым, то posix_spawn всё-равно скажет что всё в порядке, а затем надо вызвать waitpid или wait и при помощи макроса WIFEXITED узнать, произошла ли ошибка при запуске нового процесса. Проблема только в том что wait/waitpid блокирует исполнение текущей программы. Т.е если я передал в posix_spawn левый файл, то waitpid быстро вернётся и скажет что ошибка, а если передать нормальный образ, то waitpid будет ждать до бесконечности(ну, пока новый процесс не изменит своего состояния, а он этого не сделает, т.к поднялся и работает нормально). Если же в опции waitpid передать WNOHANG, то WIFEXITED всегда возвращает false =(

ну в своем описании вы сами ответили на свой вопрос: с помощью waitpid(2) этого сделать нельзя. он предназначен несколько для других целей. а именно - ожидание завершения дочернего процесса.

> Подскажите что делать, как ждать до тех пор, пока процесс либо проинициализируется либо скажет, что он не может подняться, т.е переданный образ не корректный ?

каким-то образом вручную оповестить родительский процесс о том, что дочерний действительно запустился? например, послать ему сигнал, выставить семафор в разделяемой памяти etc.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>каким-то образом вручную оповестить родительский процесс о том, что >дочерний действительно запустился? например, послать ему сигнал, >выставить семафор в разделяемой памяти etc.

А если приложение, которое я запускаю, не знает об этом. Как тогда узнать запустилось оно или нет ? Вобщем, я просто хочу поведение, аналогичное CreateProcess в винде. CreateProcess сразу возвращает запустился процесс или нет.

Sheph
() автор топика
Ответ на: комментарий от Sheph

> А если приложение, которое я запускаю, не знает об этом. Как тогда узнать запустилось оно или нет ?

тогда пойти по пути обычной последовательности fork()->exec()? зачем вам вообще нужен именно posix_spawn()?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

А как сделать это при помощи fork->exec ?

retval = fork(); if (retval == -1) { //Cannot fork } else if (retval == 0) { int ret = execv(file, arguments); //Мне нужно посмотреть в ret чтобы узнать, запустился ли процесс, но как мне это сделать ? Ведь я сейчас находусь в копии процесса, а эта информация нужна оригиналу exit(ret); } int status; waitpid(retval, &status, WNOHANG); //В status'е будет мусор :( exit(0);

Sheph
() автор топика
Ответ на: комментарий от Sheph

> retval = fork(); if (retval == -1) { //Cannot fork } else if (retval == 0) { int ret = execv(file, arguments); //Мне нужно посмотреть в ret чтобы узнать, запустился ли процесс, но как мне это сделать ?

если вам нужно посмотреть, запустился ли *процесс*, то вы это уже сделали, проверяя результат исполнения fork() retval на -1 :) после успешного fork() дочерний процесс точно запустился.

а посмотрев man на exec можно увидеть, что образ или загрузится успешно и тогда exec() не вернет управления, или же он выдаст ошибку, которую можно проанализировать, после чего при необходимости вернуть ее родительскому процессу.

http://www.opengroup.org/onlinepubs/009695399/functions/exec.html

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>после успешного fork() дочерний процесс точно запустился

Не обязательно, а если такого файла не существует fork-то выполнится, копия процесса создастся, а exec() не подменит её нужной.

>и тогда exec() не вернет управления, или же он выдаст ошибку, которую можно проанализировать

А как мне её проанализировать, если она вернётся в ФОРКНУТОЙ копии процесса, мне-то нужно анализировать в ОРИГИНАЛЕ... А если она не вернёт управления, то как я узнаю что процесс успешно загрузился ?

Вообще мне нужно чтобы работало так как CreateProcess. Т.е вот вызываю я CreateProcess и СРАЗУ знаю запустился процесс или нет, а как это сделать в линуксе ???

Sheph
() автор топика
Ответ на: комментарий от Sheph

> А как мне её проанализировать, если она вернётся в ФОРКНУТОЙ копии процесса, мне-то нужно анализировать в ОРИГИНАЛЕ...

передать статус из дочернего процесса в родительский? сингналы, сокеты, fifo, разделяемая память - все что угодно на ваш выбор.

> А если она не вернёт управления, то как я узнаю что процесс успешно загрузился ?

самое банальное - поставить таймаут? при желании можно придумать и более надежный способ.

> Вообще мне нужно чтобы работало так как CreateProcess. Т.е вот вызываю я CreateProcess и СРАЗУ знаю запустился процесс или нет, а как это сделать в линуксе ???

в *NIX загрузка исполняемого файла происходит в две стадии - сперва порождается дочерний процесс, потом уже в нем загружается образ. от этого очевидно и нужно плясать.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>самое банальное - поставить таймаут? при желании можно придумать и более надежный способ.

Вот в том то и дело, что у меня есть такое желание. Таймаут не годится...

Sheph
() автор топика
Ответ на: комментарий от Sheph

> Вот в том то и дело, что у меня есть такое желание. Таймаут не годится...

ну навскидку: создаем в родительском процессе пайп и выставляем ему флаг "close on exec". порождаем дочерний процесс, который естественно наследует этот пайп. после fork() в родительском процессе ждем одного байта из пайпа. в дочернем процессе загружаем желаемый образ через exec(). далее возможны два варианта:
1) образ нормально загрузился. в этом случае управление перейдет в загруженный образ, а пайп будет закрыт ядром и родительский процесс вместо байта статуса получит SIGPIPE или на соотв. ошибку -> поймет, что все ok.
2) образ не загрузился и управление вернулось в дочерний процесс. тогда пишем статус в пайп и выходим. в свою очередь, родительский процесс прочитает желаемый байт статуса -> поймет, что ошибка.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>1) образ нормально загрузился. в этом случае управление перейдет в загруженный образ, а пайп будет закрыт ядром и родительский процесс вместо байта статуса получит SIGPIPE или на соотв. ошибку -> поймет, что все ok.

SIGPIPE придёт только если я попытаюсь писать в pipe, а если я делаю read то я так и не узнаю закрылся он или нет, по идее по закрытии read должен вернуть 0, но у меня он почему-то блокирует =(

Sheph
() автор топика
Ответ на: комментарий от klalafuda

Всё, разобрался, спасибо огромное

Sheph
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.