Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Sambungan Python yang ditulis dalam Go mengabaikan Ctrl+C

Sambungan Python yang ditulis dalam Go mengabaikan Ctrl+C

王林
王林ke hadapan
2024-02-13 14:09:101242semak imbas

用 Go 编写的 Python 扩展会忽略 Ctrl+C

editor php Apple mendapati sambungan Python yang ditulis dalam Go mungkin menghadapi masalah semasa mengendalikan isyarat Ctrl+C. Biasanya, apabila kita menekan Ctrl+C pada baris arahan, isyarat SIGINT dihantar ke program yang sedang berjalan untuk memintanya menghentikan pelaksanaan. Walau bagaimanapun, sambungan Python yang ditulis dalam Go seolah-olah mengabaikan isyarat ini, menyebabkan program gagal berhenti dengan anggun. Isu ini adalah potensi bahaya tersembunyi untuk pembangun yang menulis sambungan Python menggunakan Go dan memerlukan perhatian khusus. Oleh itu, semasa proses pembangunan, kita harus mencari penyelesaian untuk menyelesaikan masalah ini untuk memastikan program keluar biasa.

Kandungan soalan

Saya menggunakan pemacu ular sawa yang ditulis dalam go yang bersambung ke beberapa perkhidmatan dan melakukan beberapa pemprosesan. Kami menemui masalah dengan contoh perkhidmatan yang "tidak sihat", yang menyebabkan pemandu tersangkut dan tidak dapat menamatkan melainkan kami kill prosesnya.

Melakukan beberapa eksperimen, saya mendapati bahawa apabila melaksanakan sambungan yang ditulis dalam go, program mengabaikan ctrl+c 命令,直到控制权返回到 python,而使用 c 编写的扩展则不会发生这种情况,其中在执行时引发 keyboardinterrupt c代码。我的问题是为什么会发生这种情况以及是否有办法规避这个问题或发出某种超时。尝试使用 threading.timer 引发异常来模拟超时,但问题是该异常是在它自己的线程中引发的,并且不会中断主线程。在python(cpython)3.93.10中测试。至于我写的poc扩展,go版本是1.20.4,c编译器是9.4.0 yang dipancarkan.

Saya akan tinggalkan sedikit poc di bawah.

kod python:

import ctypes

import ctypes
go_library = ctypes.cdll.loadlibrary('./go_library.so')
hello_go = go_library.helloworld

c_library = ctypes.cdll.loadlibrary("./c_library.so")
hello_c = c_library.helloworld

try:
    print("calling golang code")
    hello_go()

    print("calling c code")
    hello_c()
except keyboardinterrupt:
    print("ctrl+c issued dd:")
finally:
    print("done")

pergi sambungan

package main

import (
   "c"
   "log"
   "time"
)

func helloworld(){
   log.println("hello world")
   time.sleep(10 * time.second)
   log.println("done sleeping")
}

func main(){
}

c sambungan

#include <stdio.h>

int helloWorld() {
    printf("Hello from C\n");
    sleep(10);
    printf("Done sleeping from C\n");

    return 0;
}

Penyelesaian

Saya juga mengalami situasi yang sama. Selepas beberapa penyelidikan saya menemui penyelesaiannya.

Berdasarkan jawapan ini:

Python memasang pengendali isyarat pada sigint yang hanya menetapkan bendera yang disemak oleh gelung penterjemah utama. Agar pengendali ini berfungsi dengan betul, jurubahasa Python mesti menjalankan kod Python.

Nampaknya semasa menjalankan kod golang, golang memanggil pengendali isyarat sigint yang dipasang ular sawa untuk menetapkan bendera. Oleh itu, apabila berjalan kembali ke python, gangguan papan kekunci dikesan.

Dari dokumentasi golang:

(apabila program bukan pergi memanggil kod go) Jika pemberitahuan dipanggil untuk isyarat tak segerak, pengendali isyarat pergi dipasang untuk isyarat itu. Jika penetapan semula kemudian dipanggil pada isyarat, pengendalian asal isyarat akan dipasang semula, memulihkan pengendali isyarat tidak pergi (jika ada).

Jadi kod di bawah akan menangkap sigint dalam kod go dan mengembalikan fungsi sebaik sahaja sigint berlaku.

func helloWorld() {
    c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGINT)

    // the original handling for that signal will be reinstalled, restoring the non-Go signal handler if any.
    defer signal.Reset(syscall.SIGINT)

    go func() {
        log.Println("Hello World")
        time.Sleep(10 * time.Second)
        log.Println("Done sleeping")
        c <- nil

    }()

    // wait go routine to finish or signal received
    <-c
}

Atas ialah kandungan terperinci Sambungan Python yang ditulis dalam Go mengabaikan Ctrl+C. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam