Stop bash subshell when parent wants tty input

General Tech Bugs & Fixes 2 years ago

0 2 0 0 0 tuteeHUB earn credit +10 pts

5 Star Rating 1 Rating

Posted on 16 Aug 2022, this text provides information on Bugs & Fixes related to General Tech. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Take Quiz To Earn Credits!

Turn Your Knowledge into Earnings.

tuteehub_quiz

Answers (2)

Post Answer
profilepic.png
manpreet Tuteehub forum best answer Best Answer 2 years ago

 

I have a problem where a parent process wants input from the TTY, but the child process, being bash, which ignores SIGTTIN, keeps running and interferes. Is there a way to get bash to play nicely?

Details

This is on Alpine Linux 3.9 with bash 4.4.19.

For simplification, let's say we have the command wrapper, which does some stuff and then forks a child command. So wrapper bash essentially runs bash as a subshell.

In my situation, wrapper is itself wrapped in a function, like this:

function wrap() {
    wrapper bash -l
}

So I'm running bash at $SHLVL 1 and I type wrap which puts me at $SHLVL 2. I'm working away in the subshell with the enhancements wrapper provides. I am using the bash subshell as a regular interactive shell, so I still need job control. Disabling job control with set +m or set +o monitor is not acceptable.

The problem comes when wrapper wants to read from the TTY. It tries to read and it gets a SIGTTIN. At this point I'm kicked back into $SHLVL 1 with wrapper in the background. Unfortunately, the $SHLVL 2 bash did not get the signal, and is still outputting shell prompts, trying to read from the TTY, but is now getting EOFs causing it to quit if I'm not careful (and maybe lucky) so that my first characters are fg and bring wrapper to the foreground and reading from TTY.

This is a precarious situation and I would like something robust. I just don't know what to do. I'm on a non-graphic terminal, so I cannot just open another window. I could not get openvt to work, I guess because it expects to be running in a graphic environment. I tried writing a bash script like

#!/bin/bash -m
trap "echo parent TTIN" TTIN
bash &
wait $!

but that did not successfully wait for the bash shell to end. It returned immediately.

What I would like to have happen is that when wrapper wants to read from the terminal, the child process is suspended, and then when wrapper puts itself in the background again, the child process resumes. I'm willing to change the way wrapper is launched, or have it launch another wrapper script that then launches bash, but I have no control over wrapper itself.

profilepic.png
manpreet 2 years ago

If I understood your description correctly, I daresay that the wrapper program is not designed to spawn children that are interactive, otherwise it would take care of stopping (SIGSTOP) its children before accessing the tty and then resuming them (SIGCONT) as soon as it has finished with the tty. Apparently that is not the case, if it expects to be allowed to access the tty arbitrarily.

It can be fairly easy to make a helper program to be put between your SHLVL=1 and wrapper thus acting as cushion layer between the two so that your first shell does not detect wrapper being stopped; then this helper program would detect when wrapper gets stopped, and on such event it would stop wrapper’s children, give the tty back to wrapper and resume it. But then it wouldn’t be as well as easy to detect when wrapper has finished with the tty without active cooperation (i.e. notification) by wrapper itself. In fact, given the described behavior, I suspect wrapper actually does not put itself in the background nor does anything more than just going to sleep onto some blocking system-call.

However, if it really puts itself in the background, then the best you can do is to have the helper program continuously poll the tty about the current foreground process, and when that changes back to being wrapper's child, the helper program resumes it (if wrapper doesn’t do so itself, as I suspect).

That is, in general, for resuming the child, I’m afraid you need some specific event (or sequence of events), detectable from outside of wrapper, with which you can correctly infer that wrapper has indeed finished with the tty, and on such event(s) resume wrapper’s child.


0 views   0 shares

No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.