Here is my main.go
package main
/*
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// Global variable to store old action
struct sigaction old_action;
// Signal handler function
void handler(int signum, siginfo_t *info, void *context) {
printf("Received signal: %d\n", signum);
printf("Sent by PID: %d\n", info->si_pid);
printf("Signal code: %d\n", info->si_code);
printf("User ID: %d\n", info->si_uid);
if (info->si_pid != 0) {
char proc_status_path[256];
snprintf(proc_status_path, sizeof(proc_status_path), "/rootfs/proc/%d/status", info->si_pid);
FILE *fp = fopen(proc_status_path, "r");
if (fp == NULL) {
perror("fopen");
return;
}
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}
fclose(fp);
}
}
// Function to set up signal handling
void setup_signal_handler() {
struct sigaction action;
// Initialize the action structure
memset(&action, 0, sizeof(action));
sigfillset(&action.sa_mask); // Block all signals while the handler is executing
action.sa_sigaction = handler; // Set the signal handler function
action.sa_flags = SA_SIGINFO | SA_ONSTACK; // Set flags
// Set up the signal handler for SIGTERM
if (sigaction(SIGTERM, &action, &old_action) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
}
*/
import "C"
import "fmt"
func main() {
C.setup_signal_handler()
for {
fmt.Println("Sleeping..., waiting for signal")
C.sleep(10)
}
}
I am trying to use C language to help me to handler signal and print out the pid of signal sender. The original Go packages(syscall, os,... etc) does not provide such information. However, when I run my code above, there are two process starts up. One is go run .
and the other one is signal
, which is the name of my go package. When I send signal to go run .
, nothing happens while to signal
, informations pop up.
What I understand is that the implicity C package fork another process to run those C code. I cannot apply the signal handler in C to my go
process.
My goal is to print out informations of any kind of signal sent to my go
process. Related informations should include at least pid
, ppid
. Maybe there is another better solution for my situation.
Is there any document about cgo? I couldn't find the document that describe the process control machanism of cgo package.
[UPDATE]
Thank @kostix and @eik for answering! I tried go build
and run the binary later.
Before the handler
return, I replace the handler of SIGTERM
with the old action and raise SIGTERM
again. It works and make the Go signal.Notify succeed to push os.Signal into channel. However, When I replace the handler back to the original one, it turns out to be a recursive signal.
// ...
fclose(fp);
}
fflush(stdout);
sigaction(SIGTERM, &old_action, &action);
raise(SIGTERM);
}
However, implementation above could solve my problem. I only need to handle some signal once and then pass it to Go handler.
The process go run .
is your Go compiler. It compiles your program (including the C code) into an executable, and then runs the resulting (build) program with buildRunProgram
, which calls RunStdin
which starts a new progress with Cmd.Run
.
So wahr you are seeing is normal and signal
is your program. When you don't like this, use go build
and run it separately with ./signal
.
Edit: With cgo, the C code is in the same binary as the Go code. Since they run in the same process, the signal is delivered to only once, so only one handler receives a signal. This has nothing to do with Go or a program being written in multiple languages, try writing a C program with two signal handlers.