Когда пользователь нажимает Ctrl + C в оболочке Posix / Linux с запущенной программой, эта программа получает сигнал SIGINT. При запуске программы на основе GApplication это означает, что программа немедленно завершается.
Как я могу преодолеть это и корректно завершить работу GApplication?





Вы можете использовать g_unix_signal_add(). Эта функция принимает обратный вызов, который вызывается, когда программа получает указанный вами сигнал. (SIGINT в этом случае)
Этот обратный вызов должен затем вызывать g_application_release(), пока счетчик использования GApplication не упадет до нуля. Как только это произойдет, основной цикл завершится, и будет выдан сигнал shutdown от GApplication. Обрабатывая этот сигнал, вы можете выполнить все необходимые задачи деинициализации до завершения программы.
(взято из справочное руководство :)
GApplication provides convenient life cycle management by maintaining a "use count" for the primary application instance. The use count can be changed using g_application_hold() and g_application_release(). If it drops to zero, the application exits. Higher-level classes such as GtkApplication employ the use count to ensure that the application stays alive as long as it has any opened windows.
Пример на Вале:
public class MyApplication : Application {
public MyApplication () {
Object (flags: ApplicationFlags.FLAGS_NONE);
startup.connect (on_startup);
activate.connect (on_activate);
shutdown.connect (on_shutdown);
Unix.signal_add (
Posix.SIGINT,
on_sigint,
Priority.DEFAULT
);
}
private bool on_sigint () {
release ();
return Source.REMOVE;
}
private void on_startup () {
print ("Startup\n");
}
private void on_activate () {
print ("command line\n");
hold ();
}
private void on_shutdown () {
print ("Shutdown\n");
}
}
void main (string[] args) {
new MyApplication ().run ();
}
(компилируется с valac foo.vala --pkg gio-2.0 --pkg posix)
Это приведет к выдаче критического предупреждения, если пользователь нажмет Ctrl + C второй раз, когда приложение завершает работу. Вы должны вернуть
GLib.SOURCE_REMOVEизon_sigint(), чтобы удалить обработчик сигнала после его первого запуска - или добавить отслеживание состояния, чтобы не вызыватьrelease()чаще, чемhold().