Вот мой 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)
}
}
Я пытаюсь использовать язык C, чтобы помочь мне обработать сигнал и распечатать pid отправителя сигнала. Исходные пакеты Go (syscall, os,... и т.д.) не предоставляют такой информации. Однако, когда я запускаю приведенный выше код, запускаются два процесса. Один — go run ., а другой — signal, это имя моего пакета go. Когда я посылаю сигнал на go run ., ничего не происходит, а на signal появляется всплывающая информация.
Я понимаю, что пакет Implicity C является ответвлением другого процесса для запуска этого кода C. Я не могу применить обработчик сигнала в C к своему процессу go.
Моя цель — распечатать информацию о любом виде сигнала, отправленного в мой go процесс. Сопутствующая информация должна включать как минимум pid, ppid. Возможно, есть другое лучшее решение для моей ситуации.
Есть ли какой-нибудь документ о cgo? Мне не удалось найти документ, описывающий механизм управления процессом пакета cgo.
[ОБНОВЛЯТЬ]
Спасибо @kostix и @eik за ответы! Я попробовал go build и запустил двоичный файл позже.
Перед возвратом handler я заменяю обработчик SIGTERM старым действием и снова вызываю SIGTERM. Это работает и подает сигнал Go. Notify успешно передает os.Signal в канал. Однако когда я заменяю обработчик обратно на исходный, это оказывается рекурсивным сигналом.
// ...
fclose(fp);
}
fflush(stdout);
sigaction(SIGTERM, &old_action, &action);
raise(SIGTERM);
}
Однако приведенная выше реализация может решить мою проблему. Мне нужно только один раз обработать какой-то сигнал, а затем передать его обработчику Go.
Спасибо за комментарий! Я попробовал go build и обновил свой пост. До сих пор неясно, как обрабатывать сигнал от обработчика C и Go.
«… пакет C неявно является ответвлением другого процесса для запуска этого кода C». — нет, это определенно не тот случай. «Есть ли какой-нибудь документ о cgo?» – конечно, есть . Что касается вашего первоначального вопроса: читали ли вы документацию по os/signal относительно ее взаимодействия с кодом, отличным от Go?

Процесс go run . — это ваш компилятор Go. Он компилирует вашу программу (включая код C) в исполняемый файл, а затем запускает полученную программу (сборку) с помощью buildRunProgram , которая вызывает RunStdin , который запускает новый прогресс с помощью Cmd.Run.
Итак, то, что вы видите, — это нормально, и signal — это ваша программа. Если вам это не нравится, используйте go build и запустите его отдельно с помощью ./signal.
Обновлено: в cgo код C находится в том же двоичном виде, что и код Go. Поскольку они выполняются в одном и том же процессе, сигнал доставляется только один раз, поэтому сигнал получает только один обработчик. Это не имеет ничего общего с Go или программой, написанной на нескольких языках. Попробуйте написать программу на C с двумя обработчиками сигналов.
Спасибо за комментарий! Я попробовал go build создать исполняемый файл и запустить программу непосредственно в своей Linux-подобной среде. На этот раз есть только один процесс. Однако мне все еще нужно обрабатывать сигнал как в обработчике C, так и в Go.
Я исправил ответ. Попробуйте написать программу на чистом C с двумя обработчиками сигналов :D Также отметьте ответ как полезный, если он полезен ;)
Я понимаю, что сигнал мог быть доставлен только один раз. Пакет сигналов Go волшебным образом вызывает signal_enable в signal_unix.go. Я уверен, что golang заставляет обработчик сигнала cgo сосуществовать с обработчиком в go (с помощью invoke или других уловок). Я пытаюсь вставить os.Signal в сигнальный канал Go после того, как cgo получит его, вручную вызываю себя...
Никогда не используйте
go run. Он компилирует ваш код, запускает полученный исполняемый файл образа и затем выбрасывает его. Итак, if не создает ничего, кроме путаницы, и, следовательно, применим только в тех случаях, когда вы очень хорошо понимаете, что происходит, и довольны результатом. Просто используйтеgo build/go install+ проведите результат вручную.