XFCE Panel becomes parent of processes launched via either launchers or Whisker
By wrapping xfce4-panel
with a systemd
service unit, I discovered that any application/process launched via either regular launchers or Whisker menu would become a child of xfce4-panel
. To say that it's annoying and feels error-prone is to say nothing. Here are my observations and reasons why I believe this should be reworked:
-
Now when
xfce4-panel
is wrapped with asystemd
service unit, in thesystemd
Journal, I see output spam (essentiallystdout
andstderr
) coming from all sorts of different applications that were started viaxfce4-panel
, e.g. from Chromium:Jun 22 02:15:55 g75vw xfce4-panel[1903]: [10737:10737:0622/021555.811459:ERROR:gles2_cmd_decoder.cc(5759)] GLES2DecoderImpl::ResizeOffscreenFramebuffer failed because offscreen FBO was incomplete. Jun 22 02:15:55 g75vw xfce4-panel[1903]: [10737:10737:0622/021555.811606:ERROR:gles2_cmd_decoder.cc(3984)] ContextResult::kFatalFailure: Could not allocate offscreen buffer storage.
and this is just one small example. Essentially,
stdout
andstderr
ofxfce4-panel
become littered and overloaded with totally irrelevant stuff, not to mention journal itself. -
systemd
by default would kill children upon termination of unit. However, in context of GUI panel, launchers, menus, and etc. this does not make any sense because processes that are launched are logically not supposed to be owned by those, and should rather continue to run independently and user is supposed to take care of them as he/she started them in the first place. Hence, unless the following is added:[Service] ... KillMode=process
restarting or stopping
xfce4-panel
would cause a big bang for all applications opened so far. -
Once again, user applications are no supposed to be owned by GUI panels, launchers, menus, and etc. They should become independent top-level processes. Please, use classic
setsid
and double-forking to achieve that daemon-like behavior. For brevity, I'm plugging a quality and well-tested POSIX shell implementation of what I mean (this can be easily translated into C, plus there are plenty of reading and examples in C on that topic too):daemon() ( # -------------------------------------------------------------------------- # NOTE: # # The following snippet implements the classic and well-known daemon # spawning approach via double-forking: # # 1. 'fork' --- create the first child process that is not the process # group leader (the surrounding subshell); # 2. 'setsid' --- create the new session, set the process group ID (become # the process group leader of the newly created process group), and # execute ('execve') the specified program (the non-interactive shell to # create the second child process); # 3. 'fork' --- create the second child process to execute the actual # intended program as daemon (the non-interactive shell applying control # operator <ampersand> '&' to the positional arguments representing the # actual intended program to be executed as daemon). # # If job control is disabled (and it is here), both utility 'setsid' and # control operator <ampersand> '&' (asynchronous execution of the preceding # command) redirect the standard input, before any explicit redirection(s) # are performed, to '/dev/null'. Hence, there is no need to explicitly # apply that redirection, so only file descriptors of the standard output # and the standard error require explicit treatment: # close && CDPATH= cd -- '/' && umask 0 && \ exec setsid "${SHELL:-sh}" -e -u -c '"${@}" 1> /dev/null 2>&1 &' \ daemon "${@}" # -------------------------------------------------------------------------- )
where
close
is a function that closes all open file descriptors. You won't need to create a nested shell invocation to achieve the behavior of&
in C of course, just afork
withoutwait
.