Непредвиденная ошибка kill() в Linux

Kill(pid, 0), похоже, неправильно устанавливает код ошибки... как указано в man для kill

Ошибки

Функция kill() завершится ошибкой, если:

EINVAL Значение аргумента sig является недопустимым или неподдерживаемым номером сигнала.
EPERM У процесса нет разрешения на отправку сигнала какому-либо процессу-получателю.
ESRCH Не удается найти процесс или группу процессов, соответствующие указанному по пид. Следующие разделы информативны. 1

Он возвращает ENOENT (нет такого файла или каталога), а затем иногда возвращает EINTR (системный вызов прерван)...

Вот что я делаю:

kill(g_StatusInstance[i].pid, SIGTERM) == -1 && log_fatal_syscall("kill-sigterm");
kill(g_StatusInstance[i].pid, 0);

log_info_console( "Checking process for errors: %s\n", strerror(errno));

if(errno != ENOENT)
{
   kill(g_StatusInstance[i].pid, SIGKILL) == -1 && log_fatal_syscall("kill-sigkill");
}

Я делаю что-то неправильно?


person JonH    schedule 25.10.2012    source источник
comment
Что мешает? Что делают ваши обработчики сигналов? Что делает log_fatal_syscall()? Что-то еще настраивает ENOENT... или вы действительно имели в виду ESRCH?   -  person pilcrow    schedule 25.10.2012
comment
Вы убедились, что errno равно 0 перед вызовом kill?   -  person n. 1.8e9-where's-my-share m.    schedule 25.10.2012
comment
когда я нажимаю ctrl c, он вызывает функцию, которая делает это, и в основном есть цикл, который проходит через все процессы, запущенные в данный момент моей программой... затем убивает их   -  person JonH    schedule 25.10.2012
comment
нет, я ничего не устанавливал перед убийством   -  person JonH    schedule 25.10.2012
comment
Он возвращает ENOENT... иногда возвращает EINTER - Откуда вы знаете? Я не вижу, чтобы вы где-нибудь сохраняли результат. Типичная ошибка с errno заключается в том, что он не сохраняет копию немедленно. Последующие библиотечные или системные вызовы могут установить его, если вы не проверите его немедленно.   -  person Robᵩ    schedule 25.10.2012
comment
извините, я делаю log_info_console(Проверка процесса на наличие ошибок: %s\n, strerror(errno)); сразу после второго вызова kill - обновит вопрос.   -  person JonH    schedule 25.10.2012
comment
Кроме того, вы не проверяете возвращаемое значение из kill(). errno допустимо только в том случае, если kill() возвращает -1.   -  person Robᵩ    schedule 25.10.2012
comment
kill(pid, 0) только проверяет ошибки, сигнал не отправляется...   -  person JonH    schedule 25.10.2012
comment
Хорошо, позвольте мне сформулировать это по-другому. Вызывали ли вы какую-либо функцию настройки errno перед kill, и если да, то проверяли ли вы результат и возвращали ли errno значение 0?   -  person n. 1.8e9-where's-my-share m.    schedule 25.10.2012
comment
нет - я обновил код в вопросе, чтобы включить вызов strerror() - я вызвал kill, снова kill для проверки ошибок, затем сделал strerror...   -  person JonH    schedule 25.10.2012
comment
kill(pid, 0) выполняет только проверку ошибок — но вы игнорируете результат проверки ошибок! Вы должны проверить возвращаемое значение от kill(), чтобы определить, произошла ли ошибка.   -  person Robᵩ    schedule 25.10.2012
comment
Если kill возвращает 0, то значение errno существенно неопределенно. Это может быть ENOENT, это может быть EINTR, это может быть что угодно.   -  person Robᵩ    schedule 25.10.2012


Ответы (2)


Kill(pid, 0), кажется, неправильно установил код ошибки... Возвращает ENOENT... EINTR

Вот что я делаю:

...
kill(g_StatusInstance[i].pid, 0);
log_info_console( "Checking process for errors: %s\n", strerror(errno));

Я делаю что-то неправильно?

Да. Вы не проверяете возвращаемое значение системного вызова kill(). kill() не устанавливает для errno какое-либо конкретное значение в случае успеха.

Попробуй это:

if(kill(g_StatusInstance[i].pid, 0) == -1) {
  log_info_console( "Checking process for errors: %s\n", strerror(errno));
} else {
  log_info_console( "kill returned 0, process still alive\n" );
}

В более общем смысле вам следует проверять возвращаемое значение каждого системного или библиотечного вызова, если только не объявлено, что он возвращает void.

person Robᵩ    schedule 25.10.2012

Судя по обсуждению, ваш вопрос, скорее всего, звучит так: «Почему мой kill() не дал ожидаемого эффекта?»

Чтобы понять, почему это происходит, вы должны сначала попробовать strace в процессе, который является целью kill(). Присоедините его к существующему процессу с помощью pid или вызовите его под strace. strace покажет изменения в маске сигналов и укажет, когда поступают сигналы. Если ваш сигнал поступает, вы должны отладить процесс, на который нацелен kill(), и попытаться понять, что ожидается от установленного обработчика сигналов по умолчанию.

person Brian Cain    schedule 26.10.2012