简体   繁体   English

Python C API and gnuradio, Python starts threads that don't terminate after Py_Finalize()

[英]Python C API and gnuradio, Python starts threads that don't terminate after Py_Finalize()

When I launch a python code from C code, there are many threads that do not stop at the end of the execution of the Python code:当我从 C 代码启动 python 代码时,有许多线程在 Python 代码执行结束时不会停止:

    ps -T 20402
    PID    SPID TTY      STAT   TIME COMMAND
  20402   20402 pts/0    Rl     0:11 ./test
  20402   20427 pts/0    Sl     0:00 ./test
  20402   20428 pts/0    Sl     0:00 ./test
  20402   20443 pts/0    Sl     0:00 ./test
  20402   20458 pts/0    Sl     0:00 ./test
  20402   20461 pts/0    Sl     0:00 ./test
  20402   20464 pts/0    Sl     0:00 ./test
  20402   20471 pts/0    Sl     0:00 ./test

These threads seem to be related to the use of libraries related to gnuradio.这些线程似乎与使用与 gnuradio 相关的库有关。 Here is my code in Python:这是我在 Python 中的代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: Weather satellite
# Author: Norian
# GNU Radio version: 3.8.1.0

from gnuradio import analog
from gnuradio import blocks
from gnuradio import filter
from gnuradio.filter import firdes
from gnuradio import gr
import sys
import signal
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
import osmosdr
import time

class Weather_sat(gr.top_block):

    def __init__(self):
        gr.top_block.__init__(self, "Weather satellite")

        ##################################################
        # Variables
        ##################################################
        self.samp_rate = samp_rate = 1411200

        ##################################################
        # Blocks
        ##################################################
        self.rational_resampler_xxx_0 = filter.rational_resampler_fff(
                interpolation=208,
                decimation=441,
                taps=None,
                fractional_bw=None)
        self.osmosdr_source_0 = osmosdr.source(
            args="numchan=" + str(1) + " " + ""
        )
        self.osmosdr_source_0.set_time_now(osmosdr.time_spec_t(time.time()), osmosdr.ALL_MBOARDS)
        self.osmosdr_source_0.set_sample_rate(samp_rate)
        self.osmosdr_source_0.set_center_freq(137100000, 0)
        self.osmosdr_source_0.set_freq_corr(0, 0)
        self.osmosdr_source_0.set_gain(40, 0)
        self.osmosdr_source_0.set_if_gain(20, 0)
        self.osmosdr_source_0.set_bb_gain(20, 0)
        self.osmosdr_source_0.set_antenna('', 0)
        self.osmosdr_source_0.set_bandwidth(0, 0)
        self.low_pass_filter_0 = filter.fir_filter_ccf(
            16,
            firdes.low_pass(
                1,
                samp_rate,
                110000,
                10000,
                firdes.WIN_HAMMING,
                6.76))
        self.blocks_wavfile_sink_0 = blocks.wavfile_sink('/home/norian/Documents/GNURADIO/noaadeu.wav', 1, 20800, 16)
        self.analog_wfm_rcv_0 = analog.wfm_rcv(
            quad_rate=88200,
            audio_decimation=2,
        )



        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_wfm_rcv_0, 0), (self.rational_resampler_xxx_0, 0))
        self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_0, 0))
        self.connect((self.osmosdr_source_0, 0), (self.low_pass_filter_0, 0))
        self.connect((self.rational_resampler_xxx_0, 0), (self.blocks_wavfile_sink_0, 0))

    def get_samp_rate(self):
        return self.samp_rate

    def set_samp_rate(self, samp_rate):
        self.samp_rate = samp_rate
        self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 110000, 10000, firdes.WIN_HAMMING, 6.76))
        self.osmosdr_source_0.set_sample_rate(self.samp_rate)



def main(freq):
    top_block_cls=Weather_sat
    tb = top_block_cls()

    def sig_handler(sig=None, frame=None):
        tb.stop()
        tb.wait()
        sys.exit(0)

    signal.signal(signal.SIGINT, sig_handler)
    signal.signal(signal.SIGTERM, sig_handler)

    tb.start()
    try:
        input('Press Enter to quit: ')
    except EOFError:
        pass
    tb.stop()
    tb.wait()

And here is my C code:这是我的 C 代码:

//prgm.c
#include <stdio.h>
#include "Python.h"

int main(void) {
    Py_Initialize();

    /* add . to the path */
    PyObject* sys = PyImport_ImportModule("sys");
    PyObject* path = PyObject_GetAttrString(sys, "path");
    PyList_Insert(path, 0, PyUnicode_FromString("."));

    /* import desired function */
    PyObject* pModule = PyImport_ImportModule("main");
    PyObject* pFunc = PyObject_GetAttrString(pModule, "main");

    /* call it */
    PyObject* pArgs = Py_BuildValue("(s)", "137912500");
    PyObject_CallObject(pFunc, pArgs);
    Py_Finalize();
    fprintf(stderr,"End of python software");
    while(1);
    return 0;
}

Can you explain to me how to detect threads created by python and kill them?你能解释一下如何检测由 python 创建的线程并杀死它们吗?

I am working on Ubuntu 20.4.我正在研究 Ubuntu 20.4。

Thank you very much for your help.非常感谢您的帮助。

Perhaps gnuradio creates threads from its own C API?也许 gnuradio 从它自己的 C API 创建线程? – user23952 – 用户23952

Exactly.确切地。 GNU Radio is a heavily multithreaded application. GNU Radio 是一个高度多线程的应用程序。

Can you explain to me how to detect threads created by python and kill them?你能解释一下如何检测由 python 创建的线程并杀死它们吗?

You can "kill" processes, you can't "kill" threads - you can interrupt/join them (which is akin in the sense that it means they don't get scheduled anymore, but different in the sense that the resources allocated to them don't disappear – because threads don't hold own resources (aside from a stack), it's the process that does.你可以“杀死”进程,你不能“杀死”线程——你可以中断/加入它们(这在某种意义上是相似的,这意味着它们不再被安排,但在分配给的资源的意义上是不同的它们不会消失——因为线程不拥有自己的资源(除了堆栈),它是进程。

Note that existing threads in themselves are not inherently a problem - it's perfectly normal for a program to have dormant threads that get cleaned up on exit by the operating system and not earlier;请注意,现有线程本身并不是一个问题——程序有休眠线程在操作系统退出时而不是更早地被清理是完全正常的; threads serve various purposes, including things like handling signals, waiting for RPC connections, managing other resources... which might not even occur in your case.线程有多种用途,包括处理信号、等待 RPC 连接、管理其他资源……在您的情况下甚至可能不会发生。

Do you know how to exit the gr-osmosdr block properly?你知道如何正确退出 gr-osmosdr 块吗?

This might very well be a problem of the specific driver source encapsulated in the osmosdr source.这很可能是封装在 osmosdr 源中的特定驱动源的问题。

Probably this all exits "properly", you've not actually described anything that goes wrong!可能这一切都“正确”地退出了,您实际上并没有描述任何出错的地方!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM