问题
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 }
回答1:
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!
回答2:
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.
来源:https://stackoverflow.com/questions/57962161/why-cant-i-retrieve-my-program-that-was-suspended-from-inside-backticks