У меня есть приложение для Linux, которое открывает несколько последовательных устройств (/dev/ttyUSB
X) и читает / записывает из них. Когда я запускаю его из командной строки (Ubuntu 10.04, bash), он работает отлично.
$sudo ./my_program /dev/ttyUSB0 #sudo for permissions on the device
Я хочу, чтобы эта программа запускалась при запуске и возрождалась, если она умирает, поэтому я помещаю ее в конфигурацию Upstart (/etc/init/*
) и назвал это "my_service
".
Когда я перезагружаю машину, выполняется my_service и запускается my_program. Однако через несколько секунд (примерно когда он открывает ttyUSB и читает с них) мой процесс получает SIGINT. Я не могу понять, откуда это. Это не проблема с разрешениями на устройствах, они отлично работают с open () и несколько байтов передаются нормально. С помощью waitsiginfo()
Я смог получить si_code
0x80 или SI_KERNEL
. Итак, я знаю, что это исходит не от другого процесса, а от самого ядра. Никто не ударил CTRL-C или ALT-CTL-DEL на консоли - почему ядро отправляет мне SIGINT
?
Хуже того, моя программа соответствующим образом завершает работу на основе этого сигнала - возрождается Upstart и сразу же снова получает SIGINT! Есть ли способ выяснить, откуда исходит этот сигнал и почему? Есть ли какой-то уровень отладки ядра, который мог бы пролить свет на это? Почему отличается поведение при запуске с помощью Upstart и вручную из bash
?
Проблема решена, но это была ошибка программирования, не связанная с Upstart. Программа открывает устройство ttyUSB для необработанного (неканонического) ввода, но не сбрасывает флаг ISIG в termios. Всякий раз, когда был получен символ «CTRL-C» (0x02), ядро генерировало SIGINT и отправляло его программе. Эта проблема возникла не из bash, потому что настройки termios сохраняются в файле, и что-то должно было открыть tty и очистить бит ISIG до выполнения моей программы. Этого не происходило при запуске прямо из Upstart. Я все еще хотел бы, чтобы был какой-то лучший способ регистрации / отладки сигналов, ptrace - это только половина ответа!
Программа отправляет SIGINT, когда она помещается в фоновый режим (подумайте ^ Z). Обычно вещи, которые собираются жить как демоны, улавливают сигнал и продолжают жить.
Убедитесь, что вы можете запустить программу из интерактивной оболочки, а затем перевести ее в фоновый режим с помощью ^ Z. Вполне возможно, что он тоже умрет.
Если это окажется ответом, у вас есть 2 возможности. Если это ваша программа, вы можете перехватить SIGINT. Если у вас нет доступа к источникам, или вы не хотите тратить дополнительное время на кодирование этой функции, или вы запускаете программу на некоторых версиях виртуальной машины Java, у которых есть проблемы с сигналами, тогда оберните свою программу в сценарий, который использует screen
чтобы запустить и запустить вашу программу. Таким образом screen
уходит в фоновый режим, но ваш код обманывается, думая, что он работает на переднем плане интерактивного сеанса.