[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.
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.
I'm not using Xlib directly. Who does, these days? Barbarella uses gtk2 for its widget set.
Quote:
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.
Sounds reasonable!
Quote:
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.
Actually that's how I do it. The command is stored in a buffer, parsed to create an array of arguments, and then passed to execvp.
Quote:
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().
It would be useful to know about that, but as I am using a higher level widget set, I don't actually know whether the mouse is being grabbed or not. All I know is that the gtk_button widget picks up a gdk click event and emits a "clicked" signal, which my program responds to. I suppose I could look at the gtk2 source, but I doubt if I would understand much. My knowledge of C is pretty elementary.
Quote:
Oh, and you can see what a process is using for stdin/out by ls -l /proc/$pid/fd.
Wow, that's useful! Far easier than writing a program to do it.
Quote:
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.
That's also good advice. Presumably, if they are closed, they won't be open in any of the launched programs either. istr that file descriptors survive fork/exec, although streams don't.
Quote:
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:
....
# Close stdin/out to prevent the display manager process being
# killed by a SAK event on tty1:
exec <&-
exec >&-
...
... 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.
I'm using startx, but I could put that bit of code in if I understood it! "exec <&-" What precisely does that do? And what's a SAK event?
PS: Maybe one of the mods could move this thread to programming. I think it would be more useful there.
Last edited by hazel; 06-11-2019 at 06:13 AM.
Reason: Added PS
SAK is the "secure attention key". It's a magic-sysrq kernel sequence that kills everything on the tty it's entered on. altgr-sysreq k
Don't run it on tty1 on Slackware as it'll kill most of the daemons that rc.S/M start. It's fine to use on the other ttys and can sometimes unlock a locked up X environment.
I started work on making tty1 SAK proof which is why I created this rc.4.local, but there's so much system stuff left attached to tty1 in one form or another on slackware that it became not worth the effort. Especially as I follow the current branch which means my changes get overwritten frequently.
I like playing with Xlib, and Motif and other old toolkits. GTK seems to be a constantly moving target, Qt is C++ and I'm a C kind of guy, so neither of those really appeal to me.
Appendix: I've just done an ls -l fd on one of my barbarellas (there are four instances altogether because I have a different selection of programs on each desktop) and it gives me
So input has been closed (not by me! gtk must have done it) and both outputs go to tty1. The socket connection I assume to be to X. I have no idea what the other one is.
Does that mean that any programs launched by barbarella will try to take their input from /dev/null?
Does that mean that any programs launched by barbarella will try to take their input from /dev/null?
Yes, that's what I'd expect, so I wouldn't expect a normal program to block on a read of it. But then vim/view is a ncurses tty program and is probably getting up to all manner of shenanigans, so who knows.
again, you can use (for example) pstree to check which process started which one. Also you can check the same way the fd of any other processes (like view), so just start it again and check. I'm really interested.
OK, Pan, so here's what happens. I use barbarella to launch view and most of X goes dead. But not quite all of it. For example, I can move my mouse but not click it. I can use the keyboard to change consoles but not to write.
I went to console 2, logged in, and did a ps. I found that all the graphical stuff including the barbarellas was in state "T". And so was view. I'm not sure what that state is, but you can't kill them with a SIGTERM. You have to use SIGKILL (kill -9) and then those processes become zombies.
I checked the file descriptors for view and it just had the three standard channels, all going to /dev/tty1, which is odd when you consider that barbarella, the parent of view, has stdin set to /dev/null and not /dev/tty1.
I killed view to see if that cleared the block. It didn't. I killed the barbarellas with killall -9. Still blocked. I killed fluxbox and X went down, which cleared everything.
Any explanations?
PS: I find that state T means stopped. Just like a background job gets stopped when it tries to use the console. And I bet that's because the console belongs to X.
Last edited by hazel; 06-11-2019 at 02:26 PM.
Reason: Added PS
$ view /etc/hosts </dev/null >/dev/null 2>&1
$ echo $?
1
$ view /etc/hosts </dev/null >/dev/null
Vim: Warning: Output is not to a terminal
Vim: Warning: Input is not from a terminal
This quick test seems to suggest that view is using stderr to find its terminal, or at least it errors out with exit 1 when it can't access stderr. The second example has to be killed.
did you try pstree? Do you know what is the parent of that view process?
I told you already view inherited stdin/out from X, not from barbarella or any other process.
This is just a hunch, but try including a setpgid(0,0); after you fork() and just before you exec() in order to move the forked process into its own process group. It's possible that vim/view is generating a SIGTTIN for the entire process group when trying to read the console. That would explain your 'T' process state.
vim/view is still being naughty by duplicating stderr to stdin rather than just erroring out, but at least it'll be its only victim by doing the above.
edit: ok according to the fork() manpage the child process should get a new pgid anyway, so I'm back to scratching my head and looking confused
scratch that last bit, I misread the fork manpage.
setsid() might even be a better choice than setpgid() if you want to disassociate from the controlling terminal, which might make sense for an X11 application.
Last edited by GazL; 06-12-2019 at 08:06 AM.
Reason: edit2: scratch that I misread
GazL, you nailed it! Thank you! I put setpgid into the barbarella program and now it launches view without anything seizing up. Of course view is invisible as it hasn't got a terminal, and ps shows it as "T" aka "stopped", but nothing else is affected. Just out of interest, here are view's file descriptors:
that still not explain how and why /dev/tty1 is used.
Presumably it's used because X uses it and therefore fluxbox uses it. And everything that runs in X is a descendent of the window manager. Remember, this is Slackware so I'm starting X with startx (which is my preferred method anyway).
But that's not really the core of the problem, is it. The real problem is how X can be seized up by a trivial bug in a graphical application. That oughtn't to happen.
In Windows, if a program does something illegal, the whole system crashes and you get the blue screen of death. I read somewhere that early UNIX systems were like that too: if a program did something silly with a pointer and wrote into a major component's address space, it could bring that component down. It could even bring down the kernel and crash the whole system. That doesn't happen with Linux. So how come a program I wrote could effectively crash X?
I'd be interested to see the output of ps -u $LOGNAME -o pid,ppid,sess,pgid,tty,cmd as I have some suspicions about this, but don't want to jump the gun.
Also, can you say whether you start 'barbarella' from xinitrc, or the fluxbox 'startup' file.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.