URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 6689
[ Назад ]

Исходное сообщение
"правильный kill"

Отправлено dimonna , 20-Авг-07 17:21 
Всем привет!

Вопрос. В программе запускаю консольную команду через system("program &");
Саму программу я запускаю с nohup. Вот настает момент когда мне надо
прибить запущенную через system команду. Если я делаю с консоли руками
killall -KILL program то все ок, если я встравиваю в главную программу
такой вызов через system то тоже все ок, а вот если я в программе нахожу
PID того процесса и делаю так: kill(pid, SIGKILL) или system("kill этот_pid");
то моя программа также терминируется. Почему?

Спасибо!


Содержание

Сообщения в этом обсуждении
"правильный kill"
Отправлено Ray Dudu , 20-Авг-07 17:50 
Я конечно не уверен, но думаю, что проблема в определении ПИДа. Посему предлагаю, как вариант, использовать ф-ю fork после чего ты однозначно будешь знать ПИД потомка ну и конечно что нить из семейства ф-й exec для замены содержимого процесса.

"правильный kill"
Отправлено vic , 20-Авг-07 18:09 
>Всем привет!
>
>Вопрос. В программе запускаю консольную команду через system("program &");
>Саму программу я запускаю с nohup. Вот настает момент когда мне надо
>
>прибить запущенную через system команду. Если я делаю с консоли руками
>killall -KILL program то все ок,

Не все ок, SIGKILL это крайнее средство, останавливать следует тем сигналом который ждет утилита чтобы корректно завершить свою работу. Далее использование killall то же не очень хорошо, можно запросто и лишнее прибить, тем более не хорошо если еще и с SIGKILL.
Сделайте так чтобы не было необходимости использовать SIGKILL.

> если я встравиваю в главную программу
>такой вызов через system то тоже все ок, а вот если я
>в программе нахожу
>PID того процесса и делаю так: kill(pid, SIGKILL) или system("kill этот_pid");
>то моя программа также терминируется. Почему?

Разница между _главной_ программой и программой где вызываете kill() в чем? Это разные программы? Они в родстве? Как получаете pid процесса?


"правильный kill"
Отправлено dimonna , 20-Авг-07 18:17 
>[оверквотинг удален]
>Сделайте так чтобы не было необходимости использовать SIGKILL.
>
>> если я встравиваю в главную программу
>>такой вызов через system то тоже все ок, а вот если я
>>в программе нахожу
>>PID того процесса и делаю так: kill(pid, SIGKILL) или system("kill этот_pid");
>>то моя программа также терминируется. Почему?
>
>Разница между _главной_ программой и программой где вызываете kill() в чем? Это
>разные программы? Они в родстве? Как получаете pid процесса?

Главная программа как раз и вызывает kill, - она определяет какой из процессов открыл такой-то файл на запись, и пыдается кильнуть его - собственно именно кильнуть его и надо, а получается что сама киляется. перед килом я в лог вывожу pid и вывод команды pidof programname - поэтому я уверен что киляется именно тот процесс который был запущен через system.


"правильный kill"
Отправлено vic , 20-Авг-07 19:20 
>Главная программа как раз и вызывает kill, - она определяет какой из
>процессов открыл такой-то файл на запись, и пыдается кильнуть его -
>собственно именно кильнуть его и надо, а получается что сама киляется.
>перед килом я в лог вывожу pid и вывод команды pidof
>programname - поэтому я уверен что киляется именно тот процесс который
>был запущен через system.

1. что за насилие за попытку открытия файла? есть система прав доступа, не надо просто давать права на запись кому попало. Кстати, кто сказал что успеете кильнуть между open() и write()? =)
2. вы уже писаль что в главной все ок, вопрос про ту не главную в которой не ок :)
Пример кода или хотя бы схематичный что делаете.


"правильный kill"
Отправлено dimonna , 20-Авг-07 19:42 
>[оверквотинг удален]
>>перед килом я в лог вывожу pid и вывод команды pidof
>>programname - поэтому я уверен что киляется именно тот процесс который
>>был запущен через system.
>
>1. что за насилие за попытку открытия файла? есть система прав доступа,
>не надо просто давать права на запись кому попало. Кстати, кто
>сказал что успеете кильнуть между open() и write()? =)
>2. вы уже писаль что в главной все ок, вопрос про ту
>не главную в которой не ок :)
>Пример кода или хотя бы схематичный что делаете.

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


"правильный kill"
Отправлено tx2 , 20-Авг-07 21:09 
1) как определяешь pid? (исходник)
2) что пишет ps -jfax
3) а не пробовал пользоватся fork+exec это более грамотный способ... да и pid = fork()

"правильный kill"
Отправлено dimonna , 21-Авг-07 09:24 
>1) как определяешь pid? (исходник)

Пробовал разными способами, самый простой был: даю ключем к программе уникальный ключ а потом ps auxw|grep этот ключ получаю pid - пишу в stdout, с консоли проверяю - ошибок нет - пид правильно определяет

>2) что пишет ps -jfax

а что особенного он может написать? обычный процесс создается

>3) а не пробовал пользоватся fork+exec это более грамотный способ... да и
>pid = fork()

запуск утилиты происходит в одном из тредов программы, которому передаются указатели на колбеки и переменные с которыми он оперирует - форк этого уже не сделает, сильно много городить тогда придется.


т.е. принцип такой:

тред 1: system("program -o SOME_UNIQUE_FILE >log.log 2>&1");
и ждет пока доработает программа

тред 2:
ps auxw|grep SOME_UNIQUE_FILE
парсит, находит пид program

если делать kill(pid, SIGKILL) или system("kill -9 pid"); то и сама основная программа которая запустила program киляется, а вот если сделать system("killall -KILL program) тогда все нормально, но при этом кильнутся и остальные копии program


"правильный kill"
Отправлено vic , 21-Авг-07 11:18 
>[оверквотинг удален]
>не сделает, сильно много городить тогда придется.
>
>т.е. принцип такой:
>
>тред 1: system("program -o SOME_UNIQUE_FILE >log.log 2>&1");
>и ждет пока доработает программа
>
>тред 2:
>ps auxw|grep SOME_UNIQUE_FILE
>парсит, находит пид program

1. Так это и есть классическая схема fork() + exec(), нафига тут треды?.
2. А вы пробовали снимать утилиту другими сигналами? Все ж лучше снимать ее по SIGTERM или  SIGHUP. Еще раз SIGKILL это очень крайняя мера.
3. вопрос - SIGCHILD и др. сигналы обрабатываете?
4. запускайте strace you_program возможно увидите причину (системный вызов) из-за которой вас терминируют.
5. используйте gdb :)


"правильный kill"
Отправлено Forth , 21-Авг-07 11:27 
Если уж так уж найти никак причину не получится - снимайте приложения по SIGTERM. Их оно наверняка снимет, а у своей SIGTERM игнорируйте:)


"правильный kill"
Отправлено anonymous , 23-Авг-07 06:43 
>>3) а не пробовал пользоватся fork+exec это более грамотный способ... да и
>>pid = fork()
>
>запуск утилиты происходит в одном из тредов программы, которому передаются указатели на
>колбеки и переменные с которыми он оперирует - форк этого уже
>не сделает, сильно много городить тогда придется.

Чего форк не сделает?  Какие проблемы с форком?  Форк с тредами работает нормально -- факт.  После форка в треде родительский процесс продолжает работу как обычно, а у дочернего все треды, кроме того, где вызван форк остановлены, так что можно не волноваться про остальные треды кроме текущего.  Да будет Вам известно, system() -- это тот же fork()+exec(), только в удобной упаковке.  Запуск процесса в *nix по-другому просто не реализовать.


"правильный kill"
Отправлено vic , 23-Авг-07 10:42 
>[оверквотинг удален]
>>колбеки и переменные с которыми он оперирует - форк этого уже
>>не сделает, сильно много городить тогда придется.
>
>Чего форк не сделает?  Какие проблемы с форком?  Форк с
>тредами работает нормально -- факт.  После форка в треде родительский
>процесс продолжает работу как обычно, а у дочернего все треды, кроме
>того, где вызван форк остановлены, так что можно не волноваться про
>остальные треды кроме текущего.  Да будет Вам известно, system() --
>это тот же fork()+exec(), только в удобной упаковке.  Запуск процесса
>в *nix по-другому просто не реализовать.

Это к линух относиться. В других никсах как раз не всегда так отрабатывается fork() после pthread_create(), т.е. поведение будет иное (количество тредов после форка и т.п), да и в линух на ядре 2.2.х это вызывало проблемы, т.к. треды были не NPTL.


"правильный kill"
Отправлено dimonna , 23-Авг-07 11:20 
Спасибо всем кто помогал мне!!!

решил проблему так:
копирую запускаемую программу в именем program_УНИКАЛЬНЫЙ_ID
потом запускаю через system, не определяю ни пида ни чего другого,
а когда надо остановить - делаю system("killall -KILL program_УНИКАЛЬНЫЙ_ID")

коряво, но работает :)

Еще раз всем спасибо за помощь!!
Удачи!