Я не верю, что есть какая-либо гарантия того, что вы можете вызывать функции readline из асинхронного обработчика сигнала. (Тот факт, что он «работает», не гарантирует, что время от времени он не будет иметь катастрофических сбоев.) В общем, вы должны сделать абсолютный минимум в обработчике сигнала, например, установить флаг, чтобы указать, что сигнал имеет был получен.
Библиотека readline предоставляет переменную rl_signal_event_hook
, значением которой является функция, которая будет вызываться, когда вызов readline прерывается сигналом. Вероятно, было бы целесообразно поместить в такую функцию любой код, который изменяет состояние readline.
Но, похоже, самым безопасным решением здесь было бы организовать передачу символа Control-C непосредственно на readline без запуска SIGINT. Вы можете создать пользовательскую настройку терминала на основе структуры termios
, возвращаемой tcgetattr
, которая отключает отображение Ctrl-C на функцию INTR, либо сняв флаг ISIG
(который будет также отключите другие символы прерывания, включая Ctrl-Z) или изменив c_cc[VINTR]
на _POSIX_VDISABLE
(или какую-либо другую клавишу).
Если вы работаете в Windows и не используете Cygwin, которая включает эмуляцию termios
, вы можете использовать нативные API для включения и отключения обработки Control-C.
Затем вы можете использовать rl_bind_key
, чтобы связать Ctrl-C (то есть 3) с вашей собственной функцией. Функция должна соответствовать typedef rl_command_func_t
, который равен int(*)(int, int)
. Функция должна вернуть 0; в вашем простом случае вы, вероятно, можете игнорировать аргументы, но для записи первым является «count» (числовой аргумент, вводимый путем ввода числа, удерживая нажатой клавишу Alt), а второй - сам ключ .
Вам, вероятно, следует сделать копию структуры termios
, прежде чем изменять ее, чтобы после сброса можно было сбросить настройки терминала. Как правило, вы хотите устанавливать и восстанавливать настройки терминала при каждом вызове на readline
(что также делает сам readline
).