Detect exiting the session

Hi all:

I created a backup program using Vala, which is specifically designed to do backups into an external disk. It is also designed to allow several users to share the hard disk by storing each user’s backups in different folders, and each one with only permissions for their specific creator (thus other users can’t navigate the backups). It also tries to mount the hard disk automatically if it detects that it is connected but not mounted, to guarantee that in all cases the backups are done correctly.

The problem is that, if the hard disk is mounted automatically when the user enters its session, if (s)he exits, the disk remains mounted as that user, so when entering as another user, that new one won’t be able to access the hard disk.

My idea is to make my app to unmount the hard disk when the user closes the session, thus allowing other users to use the same hard disk.

My question is: how can I detect when the user closes the session?

It is also valid to detect when the application is killed/closed and be able to execute something in that moment (an umount command).

Thanks.

If you are implementing this as a GApplication, then you can detect it by connecting to the shutdown signal, or overriding the virtual method.

Can you show your code? or, preferably, a minimal example of how you are handling the shutdown?

Yes, here it is a minimal example. I launched it in a terminal with “nohup ./test.py &”, closed the terminal and confirmed that the program was still running, and then I closed the gnome shell session. The “nohup” text file just contained: “Gdk-Message: 19:45:36.413: Error reading events from display: Tubería rota”.

Edit: I did another test that writes the texts into a file instead of sending them to stdout, just in case, but it does exactly the same: it doesn’t work neither.

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')
import sys
from gi.repository import Gtk,Gio
import atexit

def miprint(texto):
    with open("output.txt", "a") as fichero:
        fichero.write(texto)

class miaplicacion(Gio.Application):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, application_id="org.example.myapp", flags=0, **kwargs)
        self.window = None

    def do_startup(self):
        miprint("Startup\n")
        Gio.Application.do_startup(self)

    def do_activate(self):
        miprint("Activate\n")
        self.hold()


    def do_shutdown(self):
        miprint("Shutdown\n")
        Gio.Application.do_shutdown(self)

def salida_bruta():
    miprint("brute exit\n")

atexit.register(salida_bruta)
aplicacion = miaplicacion()
aplicacion.run(sys.argv)

I’ve been trying to use logind DBUS interface, but still without luck: if I connect to the session_removed signal, if another user closes its session I receive the notification, but I can’t detect my own close.

I developed something “similar” once, but it was a mixture of systemd (to manage the service and handle sessions) + GApplication (the service itself).

Take a look, I hope it helps.

P.S. you might find this post useful.

2 Likes

This should work, you just need to check the signal arguments to ensure it’s your session:

SessionRemoved(s session_id,
               o object_path);

EDIT

Sorry, I might ave misunderstood. Are just not receiving the close signal in the session being closed?

Yes, that’s the point: I can receive the SessionRemoved signal from other sessions, but it seems that it is generated after the session itself is closed, so programs inside that session can’t receive it because they are already dead.

Also, in both wayland and X11 the program dies due to the pipe/socket being closed, so signals and atexit also doesn’t work (in fact, I checked the GDK source code that manages when Wayland connection is severed, and it does an _exit(1) https://gitlab.gnome.org/GNOME/gtk/blob/master/gdk/wayland/gdkeventsource.c#L94, so it is impossible to capture it).

If you application is a GApplication, maybe you can watch for the org.foo.Program name to be unowned on DBus?

I don’t know what do you mean with “org.foo.Program”?

Unless you specifically choose not to, a GApplication will own a name on DBus; eg. GNOME Music owns org.gnome.Music.

Part of the shutdown routine is to unown that name, so you could watch for name owner to disappear for your application ID (example: org.foo.Program) or really any application.

But if the GApplication closes the bus, is because it is already closing, so how can it detect its own bus disconnecting?

Anyway, the application does not die “normally”, but “commits suicide” when it looses the connection to the compositor. As I say, it calls “_exit()”, not “exit()”, so it exist directly, without calling any callback.

It seems like your in a situation where having your application control the mounted state of the drive is not feasible and you’re going to run into some race condition or other. Maybe you should try using systemd to handle this for you, as suggested by @tchx84 ?

1 Like

Thanks, it seems that it’s the only solution.

1 Like

Yes, AndyHolmes, it seems it is the only way of doing this.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.