I'm trying to create a process that will start with X11, will be graphical and unkillable by my own user.
More specifically, I have an urxvt drop-down terminal starting at startup and running a tmux session right away. What annoys me, is that I sometimes kill it with Alt+F4 when I forget that it is the drop-down terminal and I'm supposed to hide it instead.
Sure, I'm not losing my tmux session since i can reattach to it from another terminal, but I'd have to re-launch the drop-down terminal (with the exact config) and reattach and that's tedious.
What I would want to do, is to not be able to Alt+F4 kill this specific process.
After reading this:
Make a process unkillable on Linux
I understood that I should launch the process as belonging to another user, yet even if I manage to do that within my own X server with:
sudo xhost +local:
sudo runuser -l my-secondary-user -c urxvt
I face two unwanted behaviours:
- The process is killable by my main user (the one who owns the X session)
- The virtual terminal starts logged in as my-secondary-user (of course)
The (2) may be rectifiable – just run a command to login as my main user instead – but I have no idea on how to fix the (1).
Is there way to make this work, or another way to do what I want? I'd rather avoid having to mess with creating kernel modules if possible.
Running Arch Linux with Openbox.
EDIT
I got thinking that I may be able to make Alt+F4 not work for this specific window.
found this:
Openbox: disable Alt-F4 on per application basis
and modified my rc.xml
thus:
<keybind key="A-F4">
<action name="If">
<application class="URxvt"
title="tmux-session">
</application>
<then><!-- Do nothing for urxvt-tmux-session --></then>
<else>
<action name="Close" />
</else>
</action>
</keybind>
This works slightly better than before: I cannot Alt+F4 that terminal, but also cannot Alt+F4 any urxvt window now (guess this is because new urxvt windows are all run under the same class-name?)
Besides that I can kill everything I need from the menu bar, or right clicking into my tint panel, or, of course, by command.
But this approach means that:
- I can still kill my drop-down terminal by right clicking into the tint2 panel (maybe fixable if I make the drop-down terminal not appearing as an icon to the panel – should be possible with some research)
- I cannot Alt+F4 other terminal windows (not liking it much, but maybe acceptable)
Any ideas?
SOLUTION
I found a solution that works for me based on Dmitry's answer and my above edit:
1) i set a custom title to my urxvt:
urxvt -title urxvt-drop-down
I didn't use a custom name because it appears that the
urxvt -name urxvt-drop-down
command ignores the .Xresources file that i currently use, while -title uses it.
2) i made the Alt+F4 keybind to ignore terminals titled urxvt-drop-down.
rc.xml:
<keybind key="A-F4">
<action name="If">
<title>urxvt-drop-down</title>
<then><!-- Do nothing for urxvt-drop-down --></then>
<else>
<action name="Close" />
</else>
</action>
</keybind>
3) I made the culprit never appear in the taskbar, and since the skip_taskbar also unfocuses the window, refocused it.
rc.xml:
<application title="urxvt-drop-down">
<skip_taskbar>yes</skip_taskbar>
<focus>yes</focus>
</application>
Even though this solves the problem for me, it is essentially a workaround.
Thus I'm not yet sure if Stephane's answer is the correct one for this question.
Need to do a little research on the commands presented to understand what's being done.
I won't be using xterm though, since i want fake-transparency and drop-down capability (some kind of drop-down might be possible with xterm too i think, but transparency certainly ain't without a compositor – and i won't use a compositor)
Best Answer
If switching to
xterm
is an option, you could use the hack below. There are a few caveats though. Once you address most of them, the solution ends up quite complicated, see the final script at the end.Upon receiving the instruction to close from the window manager,
xterm
will send a SIGHUP to the process group of your-application, and only exit itself when the process returns.That assumes your-application doesn't reset the handler for SIGHUP and could have unwanted side effects for the children of your-application.
Both of which seem to be a problem if your-application is
tmux
.To work around those, you could do:
That way,
tmux
would be started in a different process group, so only thesh
would receive the SIGHUP (and ignore it).Now, that doesn't apply to
tmux
which resets the handler for those signals anyway, but in the general case, depending on your implementation ofsh
, the SIGINT, SIGQUIT signals and generally both will be ignored for your-application as thatbash
is started as an asynchronous command from a non-interactivesh
. That means you couldn't interrupt your-application with Ctrl+C or Ctrl+\.That's a POSIX requirement. Some shells like
mksh
don't honour it (at least not the current versions), or only in part likedash
that does it for for SIGINT but not SIGQUIT. So, ifmksh
is available, you could do:(though that may not work in future versions of
mksh
if they decide to fix that non-conformance).Or if you can't guarantee that
mksh
orbash
will be available or would rather not rely on behaviour that may change in the future, you can do their work by hand withperl
and for instance write anunclosable-xterm
wrapper script like:(to be called as
unclosable-xterm your-application and its args
).Now, another side effect is that that new process group we're creating and putting in foreground (with
bash -m
orsetpgrp
+tcsetpgrp
above) is no longer the session leader process group, so no longer an orphaned process group (there's a parent supposedly caring for it now (sh
orperl
)).What that means is that upon pressing Ctrl+Z, that process will be suspended. Here, our careless parent will just exit, which means the process group will get a SIGHUP (and hopefully die).
To avoid it, we could just ignore the SIGTSTP in the child process, but then if your-application is an interactive shell, for some implementations like
mksh
,yash
orrc
, Ctrl-Z won't work either for the jobs they run.Or we could implement a more careful parent that resumes the child each time it's stopped, like:
Another issue is that if
xterm
is gone for another reason than the close from the window manager, for example ifxterm
is killed or loses the connection to the X server (because ofxkill
, the destroy action of you Window manager, or the X server crashes for instance), then those processes won't die as SIGHUP would also be used in those cases to terminate them. To work around that, you could usepoll()
on the terminal device (which would be torn down whenxterm
goes):