ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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.
Hi. I wrote a curses app which used the "system" function to temporarily switch two an external program (so, as soon as the user quit the external program, he would be brought back to my application).
However, I recently split all the functionality of the app into two threads via the pthreads library. I needed to make the call to system from the second (child) thread (I don't know if it is technically considered a child thread...) But when I tried this odd things would happen: for example, if I tried to use system to open a bash prompt, the original app process would be turned into a stopped background job. (?)
I've been trying to accomplish the same thing with execl, but would appreciate any advice here. Execl, it seems, replaces the original process image. But if I use fork() with execl(), then somehow the input stream doesn't get completely passed to the new program as is the case with system.
The system() call makes the whole calling process wait until the command completes, meaning both threads are blocked. If execl() isn't working for you, you could try forking a second process, calling system() from the child, then exiting the child as soon as the command completes. This would allow your original process to continue while the new one runs.
What's probably happening is the call to system creates a fork in the same process group as the original process. It sounds like the original process isn't in the foreground to start with, thereby causing the call to system to stop the entire process group until the session leader yields control of the terminal. There isn't much you can do about that while still having access to the terminal unless you fork, setpgid, and execvp instead of system.
Kevin Barry
On second thought, system might actually be calling setpgid and while bash steals foreground your console app is stuck in the background unable to perform terminal operations. Again, not much you can do about that; two things can't control the terminal at once.
I got this working. The issue was (as the previous posts mentioned) that the terminal can only have one process reading from the terminal at any given time.
According to the setpgid(2) man page (from the Linux programmer's manual):
Quote:
A session can have a controlling terminal. At any time, one (and only one) of the process groups in
the session can be the foreground process group for the terminal; the remaining process groups are in
the background. If a signal is generated from the terminal (e.g., typing the interrupt key to gener‐
ate SIGINT), that signal is sent to the foreground process group. (See termios(3) for a description
of the characters that generate signals.) Only the foreground process group may read(2) from the
terminal; if a background process group tries to read(2) from the terminal, then the group is sent a
SIGTSTP signal, which suspends it. The tcgetpgrp(3) and tcsetpgrp(3) functions are used to get/set
the foreground process group of the controlling terminal.
In my application there are two threads. One thread is in charge of taking input from the user through getch(). The other thread is in charge of (among other things) calling system(). So system creates the new process like it is supposed to, but the first thread (and thus the original process) continues running and eventually calls getchar(). Consequently, the original app process receives the SIGTSTP signal from the terminal, and becomes a stopped background job.
So, I could continue to use system(). All I had to do, though, was to implementing locking (with a pthread mutex) to ensure that before the second thread calls system(), the first thread is blocked. Then I released the block on the first thread immediately after the system() function has returned.
(Side note: With my specific implementation of the locking, I dealt with a small issue related to the second thread having trouble being able to function correctly, since the first thread has the mutex locked over 99% of the time. I fixed this by adding in a few milliseconds of nanosleep to the first thread's loop, to ensure that the second thread has some time to get the mutex locked itself. I thought I'd mention that in case somebody else ran into the same problem.)
Yes, I've always been amazed at how a few 10ms pauses here and there can keep a program running smoothly. Out of curiosity, why do you use the terminal for two different purposes in the same program?
Kevin Barry
Yes, I've always been amazed at how a few 10ms pauses here and there can keep a program running smoothly. Out of curiosity, why do you use the terminal for two different purposes in the same program?
Kevin Barry
I'm writing this curses-based program launcher, and I want each major component displayed on the screen running in its own thread, so I can easily have cool things like complex animations, clocks, dynamic menus, etc. One thread is dedicated just to input, and it messages the other threads.
Its been challenging learning the pthreads lib (and all the associated problems) but I think it has already payed off in making several parts of the programming easier to finish and a lot more fun to write.
In the long run, you might find it useful to have one thread dedicated just to output as well. If you do, it will probably be useful to use pty's, one pair per program launch. pty's aren't trivial, but they're not rocket science.
For a smallish project with goals that you can clearly see from here, you might not want to do this. But if this project could eventually grow in complexity beyond what you see now, this might be worth it.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.