Go: 获取信号源

huangapple go评论86阅读模式
英文:

Go: Get signal origin

问题

我正在使用Go语言来启动一些脚本,当它们出现问题时会使用"alert"信号。我知道Go可以捕获这些信号,但我需要知道产生信号的进程ID。在C语言中,信号处理程序会传递一个结构体来获取产生信号的进程ID,但在Go语言中似乎不是这样的。

以下是一个示例(从信号文档中提取),它告诉我是哪个信号触发了调用,但没有任何有用的信息(比如进程ID):

package main

import (
	"fmt"
	"os"
	"os/signal"
)

func main() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	s := <-c
	fmt.Println("Got signal:", s)
	fmt.Printf("%+v\n", s)
}
英文:

I'm using Go to launch a couple of scripts and when they have some problems they use the "alert" signal, I know Go can capture those signals but I need to know the PID that originated the Signal. in C to the signal handler is passed a structure to know the pid who originated the signal but in Go looks like is not the case

package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;os/signal&quot;
)

func main() {
    
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, os.Kill)

    s := &lt;-c
    fmt.Println(&quot;Got signal:&quot;, s)
    fmt.Printf(&quot;%+v\n&quot;,s)
}

the example below (extracted from the signal doc) send me the signal who originated the call but not any useful info (like the pid)

答案1

得分: 10

不,你不能以官方支持的方式做到这一点。Go运行时需要拥有信号处理程序,并且没有以任何方式公开额外的信息。

你可能仍然可以通过设置新的信号处理程序来从C语言中实现这一点,但是我建议你非常谨慎地进行操作(参考类似于issue/7227的问题)。最好使用除信号以外的其他通信方法。

以下是基于Ian在issue 7227中的代码的部分示例:

package main

/*
#include <stdio.h>
#include <signal.h>
#include <string.h>

struct sigaction old_action;
void handler(int signum, siginfo_t *info, void *context) {
    printf("Sent by %d\n", info->si_pid);
}

void test() {
    struct sigaction action;
    sigaction(SIGUSR1, NULL, &action);
    memset(&action, 0, sizeof action);
    sigfillset(&action.sa_mask);
    action.sa_sigaction = handler;
    action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO | SA_ONSTACK;
    sigaction(SIGUSR1, &action, &old_action);
}
*/
import "C"

import (
    "os"
    "syscall"
    "time"
)

func main() {
    C.test()
    pid := os.Getpid()
    for {
        syscall.Kill(pid, syscall.SIGUSR1)
        time.Sleep(time.Second)
    }
}
英文:

No, you can't do this in an officially supported manner. The Go runtime needs to own the signal handlers, and that extra information isn't exposed in any way.

You may still be able to do this from C by setting up a new signal handler, but I would be very cautious going about this (see issues like issue/7227). You're probably better off using another method for communication other than a signal.

Here's a partial example based on Ian's code from issue 7227:

package main

/*
#include &lt;stdio.h&gt;
#include &lt;signal.h&gt;
#include &lt;string.h&gt;

struct sigaction old_action;
void handler(int signum, siginfo_t *info, void *context) {
	printf(&quot;Sent by %d\n&quot;, info-&gt;si_pid);
}

void test() {
	struct sigaction action;
	sigaction(SIGUSR1, NULL, &amp;action);
	memset(&amp;action, 0, sizeof action);
	sigfillset(&amp;action.sa_mask);
	action.sa_sigaction = handler;
	action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO | SA_ONSTACK;
	sigaction(SIGUSR1, &amp;action, &amp;old_action);
}
*/
import &quot;C&quot;

import (
	&quot;os&quot;
	&quot;syscall&quot;
	&quot;time&quot;
)

func main() {
	C.test()
	pid := os.Getpid()
	for {
		syscall.Kill(pid, syscall.SIGUSR1)
		time.Sleep(time.Second)
	}
}

huangapple
  • 本文由 发表于 2015年5月13日 23:50:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/30219751.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定