[SOLVED] What happens to stdin and stdout when you're in X
Linux - GeneralThis Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Today I discovered, quite by accident, that you can lock X up completely by invoking a command-line program without giving it a terminal. I had accidentally misconfigured one of my button-bars to launch "view" instead of "gview" (for those who don't use these, they're the read-only versions of vim and gvim). My mouse went dead, but I was still able to switch to a console with ctrl-alt-F2 and kill X. As soon as I had done so, vim appeared on console 1.
Obviously vim/view had got stuck trying to open stdout for its display. And it made me wonder just what it was trying to open and why it seized up X. Normally if a process halts, that doesn't affect other processes. Can anyone explain this?
stdout and in usually are set to the bootup tty, whereas one can configure the login gui to start a session in a different tty, so say in Slackware it starts a session in tty6 so I can switch to tty1 to see my stdout, and err to see what it going on with certain things I got running outputting to stdout.
so as you seemed to have ad vim setup to start on (reg) stdout without a terminal to start first, perhaps, so it used tty1? which would to me be the logical reason it started in tty1. but remember as I too cannot mimic this to test it, making this just just an educated guess.
It is not clear for me how to replicate what you did. How do you configure your "buttons"?
It's a program I wrote myself. I call it Barbarella. Basically it displays a row of buttons whose behaviour is determined by a configuration file. Here is the one that was wrong:
As you can see each button has a tooltip, an icon and a command to run. The commands are then executed using the system() function, which calls a shell to launch them.
BW, your explanation sounds good, especially as vim did finally appear on the console that I launched X from. But as far as I could see, it only did so after I had killed X from another console. Presumably it was queuing for the console up till then. But why did X freeze? It's quite alarming that it's so easy to stop X from working.
maybe vim tossed itself into a loop to where it locked up the screen until it finds/found a cli to launch on. with you killing your x it freed it up to continue. it might have been trying to take over the active tty so it got into an argument with x and well x said NO and locked up.
it was this one wasn't it?
Code:
(Text viewer) </home/data/icons/gvim.png> {view} (should be gview)
where you called vim and not gvim that I assume gives you a automatic terminal or window to work in. -> "view" instead of "gview" (for those who don't use these, they're the read-only versions of vim and gvim).
I've never tried it, I'm a geany kind of hacker. Hacker used in its original term and not Hollywood rendition of what a hacker is, nor the general uneducated population that uses TV and Hollywood or basically anyone else do there thinking for them.
I use geany for programming (or did; I haven't written a program for a long time). It's a brilliant development environment. But for ordinary bread-and-butter editing, I use gvim.
Ugika, you can probably replicate this by creating an icon or a menu option that launches a command line application directly, i.e. not using an xterm to run the command. I would be especially interested to know if the same thing happens when X is started via a display manager, as I don't have one on either of my systems.
if you are using startx then I'd say tty1 is your main terminal for stdout too and there is no way to switch ttys to see its output, it basically become hidden, so yeah. I'd fix that oops for your x issue.
I am not sure what lang you use for this program you wrote, but if you can do error checking I'd put something in it for checking x and what tty is running to prevent it from happening again. Though all it was was a typo in wrong app called to start, I'd think if you change it to the proper one then it shouldn't happen again.
I use nano for editing configs and such and Geany for my bash scripting and some programming, codeblocks I usually end up using if I do c or c++.
Now that's a brilliant idea. The language is C and I've just been perusing the GNU C manual to see if you can find out what terminal (if any) is being used. There are a couple of low level tests that might give me what I want. One is called isatty() and tells you if a file descriptor goes to a terminal. There's another called ttyname() which gives you the actual device.
I think I'll write a little test program with just one button and a built-in command for it to run, and then I can test this out. It will probably take me a while because I haven't done any programming for a couple of years and I'm very rusty. But I agree with you that this is a bug in my program and it ought to be fixed.
All the same, I think X should be more robust and shouldn't freeze because of such a simple error.
probably it is not a bug. stdin, stdout and stderr are all either inherited from the parent process or created (those are the terminal emulators - they create pseudo terminals and connects sdtin/out/error to that). real graphical apps must not rely on stdin/out/err since there is no associated (attached) terminal. So they need to use dialogs, log files or other tricks instead of stdout/err and they also need different method to handle [keyboard/mouse] events (instead of stdin).
running view by pressing a button directly is not a good idea. You may need to run a terminal and execute view inside. What I can imagine view inherited somehow the original stdin/out/err of X, and tried to use. view did not halt, but grabbed stdin and was waiting for some input - as usual, on tty1 in the meantime X was displayed - and locked, because stdin (and mouse) was grabbed. [next time] you ought to kill this view instead of the full X system.
Real graphical apps must not rely on stdin/out/err since there is no associated (attached) terminal. So they need to use dialogs, log files or other tricks instead of stdout/err and they also need different method to handle [keyboard/mouse] events (instead of stdin).
Actually in my experience, many graphical apps do use stderr for error messages of a debugging sort as against user errors. The output is usually set to go into a hidden file in the home directory, but you can see it displayed if you run the program from a terminal.
Quote:
running view by pressing a button directly is not a good idea. You may need to run a terminal and execute view inside.
You're telling me! I would never have done that deliberately. If I wanted to run a command line app off barbarella, I'd use xterm with the -e option. This was a spelling mistake in the configuration file; I meant to put gview and I put view.
Quote:
What I can imagine view inherited somehow the original stdin/out/err of X, and tried to use. view did not halt, but grabbed stdin and was waiting for some input - as usual, on tty1 in the meantime X was displayed - and locked, because stdin (and mouse) was grabbed. [next time] you ought to kill this view instead of the full X system.
Good idea. I'll try that. But how could a program grab a console from the running X process? That would be like if you launch a program that requires console input as a background job; it doesn't grab the console from bash because it can't. What actually happens is that the kernel stops it with a SIGTTIN. Why doesn't something like that happen with X?
PS: As far as genealogy is concerned, barbarella is a child of fluxbox, which is a transformation of ~/.xinitrc. These are my processes and they are unprivileged. Xorg belongs to root. So how could a child of barbarella steal a console from X?
Last edited by hazel; 06-10-2019 at 10:45 AM.
Reason: Added postscript
Actually in my experience, many graphical apps do use stderr for error messages of a debugging sort as against user errors. The output is usually set to go into a hidden file in the home directory, but you can see it displayed if you run the program from a terminal.
no, the output can be definitely lost, because the non-existent stdout/err will be silently ignored (by design). Obviously they will print something if there was a real terminal, but it is not required. Usually it serves debugging/troubleshooting purposes only.
Quote:
Originally Posted by hazel
Good idea. I'll try that. But how could a program grab a console from the running X process? That would be like if you launch a program that requires console input as a background job; it doesn't grab the console from bash because it can't. What actually happens is that the kernel stops it with a SIGTTIN. Why doesn't something like that happen with X?
let we have a tty (your console). X started on this tty, and therefore X will handle it (stdin/out). You will start a view in X, it will inherit stdin/out and use. In the meanwhile X knows it has a child process using stdin/out therefore X will "sleep" in the background as long as the child process is running.
A similar scenario:
you start bash in your terminal and bash will handle stdin/out. Now you start view and it will inherit stdin/out from bash and will use exclusively as long as you exit it - return to bash.
Quote:
Originally Posted by hazel
PS: As far as genealogy is concerned, barbarella is a child of fluxbox, which is a transformation of ~/.xinitrc. These are my processes and they are unprivileged. Xorg belongs to root. So how could a child of barbarella steal a console from X?
The inheritance in X is (can be) very tricky. If you are really interested just use pstree
This post is going to make some assumptions as you've not provided much information about your barberella program...
There are a number of functions in Xlib named XGrab*() that a client can call to tell the Xserver, "Hey!, I'm in control of that now". The pointer is one of the resources that can be grabbed.
One possible scenario:
Your buttonbar program grabs the pointer. It registers the click and runs system("view ..."). view is a tty based program and will probably block trying to open/read stdin for input. system() never returns control to your buttonbar, which still maintains a grab on the pointer or some other Xserver resource. Everything stops.
Now, I don't know any details about how you've written your button bar, but I can see how soemthing similar to the above could happen.
My first suggestion would be to use a fork() + exec() method to spawn your applications rather than using system(). That way even if the spawned process blocks, your main process can continue to run.
If you're using any of the XGrab*() functions don't leave them grabbed for any longer than is necessary. Grab. do what you need to do and then Ungrab().
Like I said, all conjecture based on no information. It might give you something to look at, or it could be barking up completely the wrong tree.
Oh, and you can see what a process is using for stdin/out by ls -l /proc/$pid/fd.
P.S. You might also want to consider closing stdin/out in your buttonbar program when it starts if it never use them and they're not connected to a valid source/dest.
P.P.S.
I disconnect stdin/out from xdm in a custom rc.4 when I launch it, so that things don't inherit an unusable stdin/out.
Code:
$ cat rc.4.local
#! /bin/sh
#
# rc.4 This file is executed by init(8) when the system is being
# initialized for run level 4 (XDM)
#
# Tell the viewers what's going to happen...
# echo "Starting up X11 display manager..."
# Close stdin/out to prevent the display manager process being
# killed by a SAK event on tty1:
exec <&-
exec >&-
# Start the first display manager we find:
[ -x /usr/bin/gdm ] && exec /usr/bin/gdm -nodaemon
[ -x /usr/sbin/gdm ] && exec /usr/sbin/gdm -nodaemon
[ -x /opt/kde/bin/kdm ] && exec /opt/kde/bin/kdm -nodaemon
[ -x /usr/bin/kdm ] && exec /usr/bin/kdm -nodaemon
[ -x /usr/bin/sddm ] && exec /usr/bin/sddm
[ -x /usr/X11R6/bin/xdm ] && exec /usr/X11R6/bin/xdm -config /etc/X11/xdm/themes/o_O/xdm-config -nodaemon
# error
echo "Hey, you don't have KDM, GDM, SDDM, or XDM:" \
"Can't use runlevel 4 without a display manager." 1>&2
sleep 30
# All done.
$
... connecting stdin/out to /dev/null is probably safer than closing as I've seen some poorly written programs make a right hash of file-descriptors when FD's 0 and 1 are closed. Now I'm reminded of it, I'll give thought to making that change here.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.