The signal handler for SIGINT/TERM/QUIT and, importantly, SIGPIPE tries
to write an informational message to stderr. When however stderr is
redirected to a closed pipe, this will cause (another) SIGPIPE, and in
turn the signal handler will get called again, and again and again.
Since we intend to exit rtl_fm anyways, we can just ignore this signal
from this point on.
---
Here is a small test program to verify the bug.
from subprocess import Popen, PIPE
p = Popen("rtl_test", stderr=PIPE)
# sighandler is set up after rtlsdr_open() call, so read past that
while p.stderr.readline()[:8] != b"Sampling": pass
p.stderr.close()
p.terminate() # SIGTERM -> sighandler() -> fprintf(stderr) -> SIGPIPE!
Note that the signal handler is not set up immediately, but only after
rtlsdr_open() is called. Due to line buffering/flushing on stderr, we
must read from the pipe or rtl_* will stall and SIGTERM/PIPE will still
be handled by the SIG_DFL, not triggering the write to the broken pipe.
And in case someone is wondering: Using signal(2) instead of
sigaction(2) is OK, as long as it only sets to SIG_DFL or SIG_IGN.
src/rtl_adsb.c | 1 +
src/rtl_fm.c | 1 +
src/rtl_power.c | 1 +
src/rtl_sdr.c | 1 +
src/rtl_tcp.c | 1 +
src/rtl_test.c | 1 +
6 files changed, 6 insertions(+)
diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c
index 7aea8dd..8119ac8 100644
--- a/src/rtl_adsb.c
+++ b/src/rtl_adsb.c
@@ -123,6 +123,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Signal caught, exiting!\n");
do_exit = 1;
rtlsdr_cancel_async(dev);
diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index 7c84332..037793c 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -246,6 +246,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Signal caught, exiting!\n");
do_exit = 1;
rtlsdr_cancel_async(dongle.dev);
diff --git a/src/rtl_power.c b/src/rtl_power.c
index 6204de2..df3ceb7 100644
--- a/src/rtl_power.c
+++ b/src/rtl_power.c
@@ -195,6 +195,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
do_exit++;
multi_bail();
}
diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c
index e6537ca..2c93b57 100644
--- a/src/rtl_sdr.c
+++ b/src/rtl_sdr.c
@@ -74,6 +74,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Signal caught, exiting!\n");
do_exit = 1;
rtlsdr_cancel_async(dev);
diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c
index 84f5591..8781ba9 100644
--- a/src/rtl_tcp.c
+++ b/src/rtl_tcp.c
@@ -144,6 +144,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Signal caught, exiting!\n");
rtlsdr_cancel_async(dev);
do_exit = 1;
diff --git a/src/rtl_test.c b/src/rtl_test.c
index 9b44097..b7f46ea 100644
--- a/src/rtl_test.c
+++ b/src/rtl_test.c
@@ -115,6 +115,7 @@ sighandler(int signum)
#else
static void sighandler(int signum)
{
+ signal(SIGPIPE, SIG_IGN);
fprintf(stderr, "Signal caught, exiting!\n");
do_exit = 1;
rtlsdr_cancel_async(dev);
--
2.38.1
I am trying to go back and simply install gqrx on Liux Mint v21 Vanessa
(Ubuntu Jammy) using an RTL-SDR V3. It all started I believe when I tried
to install SDR++ building it from source.
I install osmo_sdr and gr-osmosdr. I have worked my way through and
deleted some of the issues, the last one being getting rid of the osmo_sdr
binary. Deleting that removed the error I was getting with the
libgnuradio-osmosdr.0.2.0 (it was showing libgnuradio-osmosdr.0.2.0 (build
0.3build53 or something).
I am now getting an error running gqrx is "gqrx: error while loading shared
libraries: libgnuradio-blocks.so.3.10.1: cannot open shared object file: No
such file or directory". Some fragment of something I uninstalled
incorrectly is causing gqrx distribution to think that this is already
installed. If I could figure out what that is, it would be helpful.
The reason I am posting this here is because it started I believe when I
installed either osmo_sdr or gr-osmosdr.
Thank you.
Kevin