Distributors ponder a systemd change
Distributors ponder a systemd change
Posted Jun 9, 2016 7:33 UTC (Thu) by Cyberax (✭ supporter ✭, #52523)In reply to: Distributors ponder a systemd change by ras
Parent article: Distributors ponder a systemd change
The scenario is dead simple - you logout, you log in and get two copies of a process that should exist in only one instance.
      Posted Jun 10, 2016 0:57 UTC (Fri)
                               by ras (subscriber, #33059)
                              [Link] 
       > What if a user _does_ NOT want a process to survive a logout? Two scenario's: And so now you say but this is effecting a large cluster of machines the unwashed masses use - and they aren't going to do the kill.  So the sysadmin that looks after them to interrupt his tea break on occasion - until the bug fix arrives.  As a part time sysadmin myself, I have to concede this is indeed a very serious situation. Fortunately, there is a workaround.  A short PAM module: 
    import os, signal, sys, time Job done!  Well maybe.  Comparing sessions works fine for ssh, but GNOME creates many of them now.  To fix that the easiest kludge would be to kill all the user's processes when all of his sessions are gone.  It would be hacky and racey - but this is just a kludge until the real bug fix comes in.  It's a pity that's exactly what the real bug fix does. 
     
    Distributors ponder a systemd change
      
    def pam_sm_open_session(pamh, flags, argv):
        return pamh.PAM_SUCCESS
    def might_fail(func, default=None):
        try:
            return func(*args)
        except EnvironmentError:
            return default
    def session_pids():
        my_pid = str(os.getpid())
        get_proc = lambda pid, name: open("/proc/%s/%s" % (pid, name)).read()
        my_session = get_proc(my_pid,"sessionid")
        return (
            int(pid) for pid in os.listdir("/proc")
            if pid[0] >= '0' and pid[0] <= '9' and pid != my_pid
            if might_fail(lamnda: get_proc(pid, "sessionid")) == my_session
            if not "Z (zombie)" in might_fail(lambda: get_proc(pid, "status"), ""))
                
    def kill_all(sig):
        for pid in session_pids():
            might_fail(lambda: os.kill(pid, sig))
    def pam_sm_close_session(pamh, flags, argv):
        kill_all(signal.SIGTERM)
        for i in range(50):
            if not any(session_pids()):
                return pamh.PAM_SUCCESS
            time.sleep(0.1)
        kill_all(signal.SIGKILL)
        return pamh.PAM_SUCCESS
 
           