2

Coding C in VS Code on Linux.

I use;

signal(SIGINT, myhandler); 
signal(SIGHUP, myhandler); 
signal(SIGKILL, myhandler); 
signal(SIGTERM, myhandler); 

and I use VS code internal terminal, "run in terminal" option checked.

While my code running in a loop, when I send key-combo CTRL-C the execution is stopped but the signal was not caught by my code (myhandler).

I added "handle all nostop print pass" to .gdbinit file but nothing has been changed.

The question is how can I catch CTRL-C (SIGINT) sent from keyboard in my program currently being debugged in VS Code?

To elaborate I'll add my launch.json, tasks.json and main.c files, below:

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
  {
    "name": "gdb build and debug active file",
    "type": "cppdbg",
    "request": "launch",
    "program": "${fileDirname}/bin/${fileBasenameNoExtension}",
    "args": [],
    "stopAtEntry": false,
    "cwd": "${workspaceFolder}",
    "environment": [],
    "externalConsole": false,
    "MIMode": "gdb",
    "setupCommands": [
      {
        "description": "Enable pretty-printing for gdb",
        "text": "-enable-pretty-printing",
        "ignoreFailures": true
      }
    ],
    "preLaunchTask": "C/C++: gcc build active file",
    "miDebuggerPath": "/usr/bin/gdb"
  }
]

}

{
"version": "2.0.0",
"tasks": [
    {
        "type": "cppbuild",
        "label": "C/C++: gcc build active file",
        "command": "/usr/bin/gcc",
        "args": [
            "-g",
            "${workspaceFolder}/*.c",
            "-o",
            "${fileDirname}/bin/${fileBasenameNoExtension}"
        ],
        "options": {
            "cwd": "${fileDirname}"
        },
        "problemMatcher": [
            "$gcc"
        ],
        "group": {
            "isDefault": true,
            "kind": "build"
            },
        "detail": "compiler: /usr/bin/gcc"
    }
]

}

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

// function prototypes
void initialize(void);
void sigHandler(int signo);

/*************** main routine which contains the infinite loop ****************/
int main(int argc, char *argv[])
{

    initialize();
    printf("It is alive...");

    while (1)
    {
        // do something
        printf("looping...");
        usleep(10000);
    }

    return 0;

} //------------------------------- main -------------------------------------//

/**
 * Let's get ready and initialize everything.
 */
void initialize(void)
{
    signal(SIGINT, sigHandler);
    signal(SIGHUP, sigHandler);
    signal(SIGKILL, sigHandler);
    signal(SIGTERM, sigHandler);
}


/**
 * Stop before exiting and close everything.
 */
void sigHandler(int signo)
{
    printf("Caught signal: %d, exiting!", signo);
    exit(0);
}
Cem
  • 23
  • 4
  • 1
    Does your code work outside the VS Code integrated terminal? – starball Feb 01 '23 at 19:54
  • 1
    What's the value of your `terminal.integrated.sendKeybindingsToShell"` setting in VS Code, and what happens if you try different values? – starball Feb 01 '23 at 19:55
  • Please show `myhandler()`, better a complete [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Weather Vane Feb 01 '23 at 19:59
  • My code works as it should be in Code blocks. my Handler() function does some clening and closing work and print "I caught a signal with number x". – Cem Feb 01 '23 at 21:44
  • Maybe this is not the main problem, but printf() is not safe in signal handlers. See also https://stackoverflow.com/questions/39987169/using-printf-as-re-entrant-function-c – ulix Feb 01 '23 at 22:43
  • I'm pretty sure it does not execute myhandler(). Because not just printf() but also none other stuff is being done. – Cem Feb 02 '23 at 08:10

1 Answers1

0

This is not documented, but using handle all skips signals used by the debugger, this can be seen in the GDB source code here.

As SIGINT is used by the debugger, this means that GDB is still intercepting the SIGINT you send, and not forwarding it to your program.

You have two choices, one is to use:

handle SIGINT ...etc...

to specifically pass through SIGINT. I'd suggest going with handle SIGINT stop print pass, this way you'll still be able to interrupt your application with Ctrl-C, but when you continue GDB will pass the SIGINT through.

If you are sure you want to handle all signals as nostop print pass though, then it turns out that GDB actually accepts multiple signals for the handle command, so you could do:

handle all SIGINT SIGTRAP nostop print pass

Your other choice could be to use signal SIGINT after stopping the program, this will resume the program but pass SIGINT just this one time. The signal command is documented here.

Andrew
  • 3,770
  • 15
  • 22