You have several problems with your signal handler and how you're setting it up.
As I already noted in comments, a signal handler can safely access a file-scope variable such as global
only if that variable is volatile
and has type sig_atomic_t
. If it attempts to access any other variable then there is a risk that it will not see the most recent value set for that variable, that code outside the scope of the handler will not see the value, if any, that the handler writes to that variable, and that the value of the variable will be corrupted as a result of the signal-handler's writes to it being non-atomic.
A more serious problem, also already noted in comments, is that specifying the SA_SIGINFO
flag to sigaction()
, as you do, tells it that you have specified the handler via the sa_sigaction
member of your struct sigaction
, whereas you have actually specified it via the sa_handler
member. If you specify the handler via sa_handler
then you must omit SA_SIGINFO
from the flags, and vice versa. If you specify the the SA_SIGINFO
flag inappropriately then receipt of the signal will cause undefined behavior, either by calling your handler with the wrong number of arguments or by trying to call a function via a garbage function pointer.
Furthermore, all functions called by a signal handler must be async-signal-safe. The entry for 'signal' in chapter 7 of the manual contains a list of functions that are safe to call, and printf()
is not among them.
But the main issue interfering with your desire that
":"should show up own automatically on the next line after I press ctrl-z
appears to be that you've included SA_RESTART
among the sigaction flags. That flag causes (some) system functions that are interrupted by receipt of the signal to be automatically restarted after the signal handler finishes, instead of returning an EINTR
error or a partial result to their callers. In your particular case, if your shell receives a SIGSTP
while reading a command, restarting the read means that control does not return to the shell for it to print a new prompt. It may very well also mean that characters entered before the ^Z are lost, depending on details of how you read the command.
Additionally, from your program's messaging, it seems like you may have a misconception about the meaning and use of ^Z and the SIGSTP
by the terminal interface and the standard shell. These serve a job-control function for jobs executed by the shell; they are not primarily about the mode of the shell itself. There is no need for the shell to maintain a flag or to behave differently after receiving a ^Z (outside the scope of the signal handler itself) -- the needed interactive behavior follows primarily from the fact that the shell can read from the standard input only when it is in the foreground.
When the shell receives a SIGSTP
,
- if it is in the foreground, it should do nothing (and avoid losing unprocessed input).
- if it is in the background, it should send a
SIGSTOP
(note the difference) to the foreground process group, and put itself back in the foreground if necessary. It may in this case emit a message and / or prompt.