Обработать завершение сессии в Linux

September 12th, 2011 Begemot Posted in Oбщее

Пытаюсь тут портировать на линукс свой менеджер заметок написанный на с++ and wxWidgets. Столкнулся с тем что не могу отследить событие когда пользователь уходит – logout, reboot, shut down. А мне то надо как-то данные сохранять. Под виндой, есть EVT_QUERY_END_SESSION, библиотека ловит виндовое сообщение и сообщает мне о событии, пускай с большими проблемами но что-то сделать можно – сохранить данные, корректно закрыть приложение, заповним положение\размеры окна и мелкие настройки. Под макосом не пробовал, но говорят работает. Под Линуксом нет – в инете полно вопросов, жалоб – но решения нет.

Пытался использовать средства gtk (или posix, или чье это там), типа

#include <stdio.h> // for File I/O #include <signal.h> // for signals #include <unistd.h> // for sleep() void handler(int sig) { /* Just print to stderr and redirect 2>> test.txt in the shell */ fprintf(stderr, "got %d\n", signal); signal(sig, handler); // let signal be caught again } int main() { signal(SIGTERM,handler); signal(SIGINT,handler); signal(SIGQUIT, handler); // Maybe we're getting QUIT first? signal(SIGHUP, handler); // If the terminal closes, we might get this signal(SIGPIPE, handler); // Don't know why we'd get this, but check anyway while(1) // loop forever with most signals trapped, impolitely waiting for a kill -9 😉

// run }

Не фига, когда руками прибиваю приложение Ctrl+c в терминале или kill … срабатывает, когда вырубаю систему нет, сообщения не получаю. В инете все пишут тоже самое не работает.  Code::Blocks тоже не сохраняет данные, если что-то изменить и сделать logout.  

Получается линукс, или убунта, или гном не дает возможность приложению узнать что сессия завершается и корретно завершить работу, сохранив данные. Вот вам и Linux with a human face 🙁

Есть правда какой-то EggSMClient в виде сорцов, LGPL, его например использует GEdit и молодец, корректно обрабатывает все. Но что-то про EggSMClient ни упоминаний толком, ни документации – особенно ничего не находится, а так разобратся без бутылки не получается. Печально все это 🙁

Related:

Posted in Oбщее | Tags: ,

9 Responses to “Обработать завершение сессии в Linux”

  1. Мне кажется, что как раз kill десктопная программа не должна ловить (это нештатное завершение), а обработка выхода из программы теоретически должна производиться переопределением wxApp::OnExit() – при штатном выходе она должна отрабатывать. Нет?

  2. В мане написано: “All processes are first notified that the system is going down by the signal SIGTERM.”.
    В моей убунте 11.04 и арче все процессы получают sigterm перед sigkill при выключении и перезагрузке.
    Алсо в мане shutdown: “-t sec Tell init(8) to wait sec seconds between sending processes the warning and the kill signal, before changing to another run‐level.”.
    То есть можно задавать через сколько секунд после sigterm будет послан sigkill.

  3. При логауте sigterm, кстате, не посылается. Посылается sighup. По умолчанию он закрывает программу, однако на него можно забить и тогда программа будет продолжать висеть в процессах, но поменяет родителя.

  4. как показывает эксперимнты OnExit не вызывается, при шутдауне, ребуте, логауте.
    SIGTERM и sighup тоже, по крайней мере вышеприведенный код ловит их если послать вручную, или запустить программу из терминала и нажать Ctrl+c, но не ловит (или не может записать данные в конфиг) если сделать что-то из перечисленного в первой строке:(

  5. Алексей Says:

    100% видел, потому что Nikolay (имя создателя топика) – это его логин на форуме.

  6. Да, видел, не помогло 🙂

  7. Тогда, может быть, имеет смысл сменить концепцию – ловить что-нибудь типа OnIdle и проверять, есть ли несохраненная инфа. Если есть – сбрасывать на винт успокаиваться, не дожидаясь, когда система будет выключаться (на современных ноутбуках с нормальной системой это событие может быть довольно редким, а от отключения питания такой подход защищает лучше 😉

  8. Программа и так сохраняет данные когда пользователь минимизирует окно или просто переключается на новую заметку. сохранять по OnIdle мне кажется сильно часто…