'Why can't I start the top command in batch mode, stop it, and then resume it with fg?

I don't know why, so I would like to ask Gen...

$ top -b

and then Ctrl + Z to stop it, and then bring it back to foreground with

$ fg %1

It does not work as desired. The screen seems to be broken, and above all, it will not accept input such as Ctrl + C. If you know why, please let me know...

(First post)



Solution 1:[1]

Seems like it's a small bug in top.

See source code top.c:

 645         /*
 646          * Catches:
 647          *    SIGTSTP, SIGTTIN and SIGTTOU */
 648 static void sig_paused (int dont_care_sig) {
 661    fflush(stdout);
 662    raise(SIGSTOP);
 663    // later, after SIGCONT...
 664    if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &Tty_raw))
 665       error_exit(fmtmk(N_fmt(FAIL_tty_set_fmt), strerror(errno)));
 666 #ifndef RMAN_IGNORED
 667    putp(Cap_rmam);
 668 #endif
 669    if (keypad_xmit) putp(keypad_xmit);
 670    putp(Cursor_state);
 671    Frames_signal = BREAK_sig;
 672    (void)dont_care_sig;
 673 } // end: sig_paused
 ...
3798    // lastly, establish a robust signals environment
3799    memset(&sa, 0, sizeof(sa));
3800    sigemptyset(&sa.sa_mask);
3801    //with user position preserved through SIGWINCH,we must avoid SA_RESTART
3802    sa.sa_flags = 0;
3803    for (i = SIGRTMAX; i; i--) {
3804       switch (i) {
....
3810          case SIGTSTP: case SIGTTIN: case SIGTTOU:
3811             sa.sa_handler = sig_paused;
3812             break;
....
3823       }
3824       sigaction(i, &sa, NULL);
3825    }

This is what happens:

  1. In line 3810, top explicitly registers its SIGTSTP handler sig_paused().
  2. When CTRL-Z is pressed, it sends SIGTSTP to top -b.
  3. When top receives SIGTSTP, in sig_paused() it stops itself by sending SIGSTOP (line 662).
  4. fg sends SIGCONT to top and wakes it up.
  5. In line 664 when top is waken up, it puts the tty in raw mode (it should not do this when -b is specified).
  6. When the tty is in raw mode, keys like CTRL-C will not generate SIGINT so CTRL-C cannot kill it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1