简体   繁体   中英

Why can't I retrieve my program that was suspended from inside backticks?

I created a program that takes a list of arguments and put them in a grid on a new tty where I can move around and select from it what I want.

When I run the program without backticks like this...

$> ./ft_select arg_1 arg_2 ... arg_N

A new tty is opened and a grid is shown...

arg_1  arg_2  arg_3
arg_4  arg_5  arg_6
arg_7  ...    arg_N

I hit ctrl+z and the program gets suspended with no problem and fg command puts it back.

My problem is that when I put the command between backticks and I try to suspend it, it get stuck without giving the prompt back.

I have to mention that I write all the content of the grid on /dev/tty

You can find in the code below the function that does the signal handling.

 23 void    signalhandler(int sig)
 24 {
 25 //  struct winsize  ws;
 26
 27     if (sig == SIGWINCH)
 28     {
 29 //      ioctl(g_data->tty, TIOCGWINSZ, &ws);
 30         update_data(g_data);
 31         print_args(g_data);
 32         update_cursor(g_data, 1);
 33     }
 34     else if (sig == SIGTSTP)
 35     {
 36         signal(SIGTSTP, SIG_DFL);
 37         enable_cap("te");
 38         modify_main_caps(SET, g_data->tty);
 39         ioctl(g_data->tty, TIOCSTI, "\032");
 40     }
 41     else if (sig == SIGCONT)
 42     {
 43         signal(SIGTSTP, signalhandler);
 44         modify_main_caps(UNSET, g_data->tty);
 45         update_data(g_data);
 46         print_args(g_data);
 47         update_cursor(g_data, 1);
 48     }
 49     else if (sig == SIGINT)
 50     {
 51         enable_cap("te");
 52         modify_main_caps(SET, g_data->tty);
 53         exit(EXIT_FAILURE);
 54     }
 55 }

CTRL + Z causes the terminal device driver to send a SIGTSTP to all processes in the foreground process group. In bash and zsh , at least, commands in a command substitution $(<command>) are executed in a subshell, but they don't get their own process group (they run in the same process group as the parent shell itself). That means that CTRL + Z should not affect them at all - press it and nothing happens, just like pressing CTRL + Z in a shell prompt doesn't do anything: in both cases, there is no foreground process group to suspend!

I think you're looking at a variation of the issue discussed in this question .

Putting a command in backquotes isn't just another way to run it; it tells the shell to run that command in a subshell and substitute the results. This is called command substitution , and can also be represented as $(command) (this syntax is more modern and usually preferred ).

The main use of command susbtitution is that it lets you use the output of one command as the input to another. For example, look at the results of these commands:

echo "1 + 1 = $(expr 1 + 1)" # prints "1 + 1 = 2"
echo "2 + 2 = `expr 2 + 2`"  # prints "2 + 2 = 4"
echo "1 + (4 / 2) = $(expr 1 + $(expr 4 / 2))" # prints "1 + (4 / 2) = 3"

When you use command substitution in place of the command itself, the the expansion still works, attempting to run the command and include its output in the shell's input. So when you run your command in a substitution, it tries to run your command, taking all of its input, then should try to run whatever it prints as the result.

I'm not exactly sure what happens when you try to suspend these, but my testing gave some unusual behaviors: trying to suspending $(cat) did nothing, but suspending $(rlwrap cat) crashed, and left the terminal confused after I killed it. But I do know that subshells aren't managed along with actual shell jobs, so you won't be able to manage a command that you run in a subshell.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM