Search code examples
csignalszsh

Why do I receive two SIGCONT signals?


I'm writing a program that sets terminal attributes so I have to reset the terminal any time the script exits, including if the user presses ^Z, but when I re-enter the command with fg, the SIGCONT signal gets sent two times, but I'm only expecting it to be called 1 time. Why is it happening twice? Here is a short program that shows the problem:

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

void sigtstp (int signum) {
    write(1, "got a SIGTSTP\n", 14);
    kill(getpid(), SIGSTOP);
}

void sigcont (int signum) {
    write(1, "got a SIGCONT\n", 14);
}

int main (int argc, char **argv) {
    signal(SIGTSTP, sigtstp);
    signal(SIGCONT, sigcont);
    while (1) {
        sleep(100);
    }
}

output is like this:

% clang cont.c -o cont
% ./cont
^Zgot a SIGTSTP
zsh: suspended (signal)  ./cont
% fg
[5]    continued  ./cont
got a SIGCONT
got a SIGCONT
^C

I'm using zsh on macOS.


Solution

  • This is a known bug in zsh versions 5.7, 5.7.1, 5.8, and 5.8.1. It was fixed by Erik Paulson for zsh 5.9:

    https://www.zsh.org/mla/workers/2021/msg01255.html

    On Ubuntu 20.04 - 22.04 this zsh bug causes fg to sometimes fail to restore a stopped vim. For some unknown reason the extra SIGCONT causes vim to immediately stop itself again.