Python C API 和 gnuradio,Python 启动在 Py_Finalize() 之后不终止的线程
Python C API and gnuradio, Python starts threads that don't terminate after Py_Finalize()
当我从 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
这些线程似乎与 gnuradio 相关库的使用有关。
这是我在 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()
这是我的 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;
}
你能给我解释一下如何检测由 python 创建的线程并杀死它们吗?
我正在研究 Ubuntu 20.4。
我使用的是 gnuradio 3.8 版,我是从 apt 安装的。
非常感谢您的帮助。
Perhaps gnuradio creates threads from its own C API? – user23952
没错。 GNU Radio 是一个高度多线程的应用程序。
Can you explain to me how to detect threads created by python and kill them?
你可以“杀死”进程,你不能“杀死”线程 - 你可以 interrupt/join 它们(这在某种意义上是类似的,这意味着它们不再被调度,但不同的是分配给它们的资源不会消失的感觉——因为线程不拥有自己的资源(除了堆栈),而是进程。
请注意,现有线程本身并不是天生的问题 - 一个程序有休眠线程是完全正常的,这些线程在退出时被操作系统清理,而不是更早;线程有多种用途,包括处理信号、等待 RPC 连接、管理其他资源......这些在您的情况下甚至可能不会发生。
Do you know how to exit the gr-osmosdr block properly?
这很可能是osmosdr源码封装的具体驱动源码的问题
可能这一切都“正常”退出,您实际上并没有描述任何出错的地方!
当我从 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
这些线程似乎与 gnuradio 相关库的使用有关。 这是我在 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()
这是我的 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;
}
你能给我解释一下如何检测由 python 创建的线程并杀死它们吗?
我正在研究 Ubuntu 20.4。 我使用的是 gnuradio 3.8 版,我是从 apt 安装的。
非常感谢您的帮助。
Perhaps gnuradio creates threads from its own C API? – user23952
没错。 GNU Radio 是一个高度多线程的应用程序。
Can you explain to me how to detect threads created by python and kill them?
你可以“杀死”进程,你不能“杀死”线程 - 你可以 interrupt/join 它们(这在某种意义上是类似的,这意味着它们不再被调度,但不同的是分配给它们的资源不会消失的感觉——因为线程不拥有自己的资源(除了堆栈),而是进程。
请注意,现有线程本身并不是天生的问题 - 一个程序有休眠线程是完全正常的,这些线程在退出时被操作系统清理,而不是更早;线程有多种用途,包括处理信号、等待 RPC 连接、管理其他资源......这些在您的情况下甚至可能不会发生。
Do you know how to exit the gr-osmosdr block properly?
这很可能是osmosdr源码封装的具体驱动源码的问题
可能这一切都“正常”退出,您实际上并没有描述任何出错的地方!