Setting up handlers for signals SIGTSTP and SIGCONT

Hi,

I am writing a script which displays one line of information and then prompts the user for input. For instance:

Information here.
Prompt: <blinking-cursor>

In Python code:

print(‘Information here.’)
input(‘Prompt: ‘)

At the input prompt, it is possible that the user presses CTRL-Z to suspend and then runs fg to resume later. I want the suspension to display a “Suspended” message, like so:

Information here.
Prompt: ^Z
Suspended.
[1]+    Stopped                python script.py

And when the script resumes again, I want the same one line of information displayed again, along with the prompt:

$ fg
python script.py
Information here.
Prompt: <blinking-cursor>

I believe that I need to set up handlers for the SIGTSTP and SIGCONT signals, in order to get this effect. I’ve come up with the following:

def sigtstp_handler(signum, frame):
    print(‘\nSuspended.’, end=‘’)
    signal.signal(signal.SIGTSTP, signal.SIG_DFL)
    signal.raise_signal(signal.SIGTSTP)
signal.signal(signal.SIGTSTP, sigtstp_handler)

def sigcont_handler(signum, frame):
    print(‘Information here.’)
    print(‘Prompt: ‘, end=‘’)
signal.signal(signal.SIGCONT, sigcont_handler)

print(‘Information here.’)
print(‘Prompt: ‘)

With this, the suspension works out the way I want it, but when I try to resume:

$ fg
python script.py
Information here.
<blinking-cursor>

i.e. the prompt is not displayed. If I hit ENTER at the blinking cursor:

$ fg
python script.py
Information here.

Prompt: $

i.e. the prompt is displayed after the input is taken from the user. (The $ at the end is the shell prompt getting printed after the script finishes running.)

Why is this happening and how do I fix this?

Thanks!

I tried the equivalent code in C:

#include <stdio.h>
#include <signal.h>

void sigtstp_handler(int signum)
{
    printf(“\nSuspended.”);
    signal(SIGTSTP, SIG_DFL);
    raise(SIGTSTP);
}

void sigcont_handler(int signum)
{
    printf(“Information here.\n”);
    printf(“Prompt: “);
}

int main()
{
    char s[20];

    signal(SIGTSTP, sigtstp_handler);
    signal(SIGCONT, sigcont_handler);

    printf(“Information here.\n”);
    printf(“Prompt: “);
    scanf(“%s”, s);
    return 0;
}

Running this, when I try to suspend, I get:

Information here.
Prompt: ^Z

[1]+    Stopped                ./a.out

i.e. the “Suspended” message is not printed. When I try to resume:

$ fg
./a.out
Suspended.Information here.
<blinking-cursor>

i.e. the prompt is again not displayed, but the “Suspended” message is displayed here.

I think this might have to do with stdout line-buffering, so I try to turn it off:

int main()
{
    …
    signal(SIGTSTP, sigtstp_handler);
    signal(SIGCONT, sigcont_handler);
    setbuf(stdout, NULL);
    …
}

Now when I compile and run it:

Information here.
Prompt: ^Z
Suspended.
[1]+    Stopped               ./a.out
$ fg
./a.out
Information here.
Prompt: <blinking-cursor>

Everything works out - the “Suspended” message is printed in the right place and the prompt is also shown in the right place while resuming.