[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r6201 - in gnuradio/trunk: . gnuradio-core/src/lib/run
From: |
eb |
Subject: |
[Commit-gnuradio] r6201 - in gnuradio/trunk: . gnuradio-core/src/lib/runtime |
Date: |
Tue, 28 Aug 2007 18:42:12 -0600 (MDT) |
Author: eb
Date: 2007-08-28 18:42:11 -0600 (Tue, 28 Aug 2007)
New Revision: 6201
Modified:
gnuradio/trunk/configure.ac
gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h
gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc
gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h
gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
Log:
trial fix for ticket:137. Merged -r6196:6200 from eb/signal to trunk
Modified: gnuradio/trunk/configure.ac
===================================================================
--- gnuradio/trunk/configure.ac 2007-08-29 00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/configure.ac 2007-08-29 00:42:11 UTC (rev 6201)
@@ -130,7 +130,7 @@
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize
sysconf])
AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler])
-AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask])
+AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask pthread_sigmask])
AC_CHECK_FUNCS([sched_setaffinity])
AC_CHECK_LIB(m, sincos, [AC_DEFINE([HAVE_SINCOS],[1],[Define to 1 if your
system has `sincos'.])])
Modified: gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h
2007-08-29 00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h
2007-08-29 00:42:11 UTC (rev 6201)
@@ -60,9 +60,30 @@
void connect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
+
void disconnect(gr_basic_block_sptr src, int src_port,
gr_basic_block_sptr dst, int dst_port);
+
+ /*!
+ * Lock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be restarted automatically.
+ *
+ * N.B. lock() and unlock() cannot be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
virtual void lock();
+
+ /*!
+ * Lock a flowgraph in preparation for reconfiguration. When an equal
+ * number of calls to lock() and unlock() have occurred, the flowgraph
+ * will be restarted automatically.
+ *
+ * N.B. lock() and unlock() cannot be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
+ */
virtual void unlock();
gr_flat_flowgraph_sptr flatten() const;
Modified: gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
2007-08-29 00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
2007-08-29 00:42:11 UTC (rev 6201)
@@ -54,16 +54,46 @@
void *
gr_scheduler_thread::run_undetached(void *arg)
{
- // First code to run in new thread context
+ // This is the first code to run in the new thread context.
- // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
-#ifdef HAVE_SIGPROCMASK
+ /*
+ * In general, on a *nix system, any thread of a process can receive
+ * any asynchronous signal.
+ *
+ *
http://www.serpentine.com/blog/threads-faq/mixing-threads-and-signals-unix/
+ * http://www.linuxjournal.com/article/2121
+ *
+ * We really don't want to be handling asynchronous signals such
+ * as SIGINT and SIGHUP here. We mask them off in the signal
+ * processing threads so that they'll get handled by the mainline
+ * thread. We leave the synchronous signals SIGQUIT, SIGBUS,
+ * SIGILL, SIGSEGV etc alone
+ *
+ * FIXME? It might be better to mask them all off in the parent
+ * thread then dedicate a single thread to handling all signals
+ * using sigwait.
+ */
+#if defined(HAVE_PTHREAD_SIGMASK) || defined(HAVE_SIGPROCMASK)
sigset_t old_set;
sigset_t new_set;
+ int r;
sigemptyset(&new_set);
sigaddset(&new_set, SIGINT);
- sigprocmask(SIG_BLOCK, &new_set, &old_set);
+ sigaddset(&new_set, SIGHUP);
+ sigaddset(&new_set, SIGPIPE);
+ sigaddset(&new_set, SIGALRM);
+ sigaddset(&new_set, SIGCHLD);
+
+#ifdef HAVE_PTHREAD_SIGMASK
+ r = pthread_sigmask(SIG_BLOCK, &new_set, &old_set);
+ if (r != 0)
+ perror("pthread_sigmask");
+#else
+ r = sigprocmask(SIG_BLOCK, &new_set, &old_set);
+ if (r != 0)
+ perror("sigprocmask");
#endif
+#endif
// Run the single-threaded scheduler
d_sts->run();
return 0;
@@ -72,7 +102,7 @@
void
gr_scheduler_thread::stop()
{
- if (GR_SCHEDULER_THREAD_DEBUG)
+ if (0 && GR_SCHEDULER_THREAD_DEBUG) // FIXME not safe to call from
signal handler
std::cout << "gr_scheduler_thread::stop() "
<< this << std::endl;
d_sts->stop();
Modified: gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc
2007-08-29 00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc
2007-08-29 00:42:11 UTC (rev 6201)
@@ -46,6 +46,9 @@
gr_top_block::~gr_top_block()
{
+ stop();
+ wait();
+
delete d_impl;
}
Modified: gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h 2007-08-29
00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h 2007-08-29
00:42:11 UTC (rev 6201)
@@ -47,37 +47,43 @@
~gr_top_block();
/*!
- * Start the enclosed flowgraph. Creates an undetached scheduler thread for
- * each flow graph partition. Returns to caller once created.
+ * \brief The simple interface to running a flowgraph.
+ *
+ * Calls start() then wait(). Used to run a flowgraph that will stop
+ * on its own, or to run a flowgraph indefinitely until SIGINT is
+ * received.
*/
+ void run();
+
+ /*!
+ * Start the contained flowgraph. Creates one or more threads to
+ * execute the flow graph. Returns to the caller once the threads
+ * are created.
+ */
void start();
/*!
- * Stop the running flowgraph. Tells each created scheduler thread
- * to exit, then returns to caller.
+ * Stop the running flowgraph. Notifies each thread created by the
+ * scheduler to shutdown, then returns to caller.
*/
void stop();
/*!
- * Wait for a stopped flowgraph to complete. Joins each completed
- * thread.
+ * Wait for a flowgraph to complete. Flowgraphs complete when
+ * either (1) all blocks indicate that they are done (typically only
+ * when using gr.file_source, or gr.head, or (2) after stop() has been
+ * called to request shutdown.
*/
void wait();
/*!
- * Calls start(), then wait(). Used to run a flowgraph that will stop
- * on its own, or to run a flowgraph indefinitely until SIGKILL is
- * received().
- */
- void run();
-
- /*!
* Lock a flowgraph in preparation for reconfiguration. When an equal
* number of calls to lock() and unlock() have occurred, the flowgraph
* will be restarted automatically.
*
- * N.B. lock() and unlock() cannot be called from a flowgraph thread or
- * deadlock will occur when reconfiguration happens.
+ * N.B. lock() and unlock() cannot be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
*/
virtual void lock();
@@ -86,8 +92,9 @@
* number of calls to lock() and unlock() have occurred, the flowgraph
* will be restarted automatically.
*
- * N.B. lock() and unlock() cannot be called from a flowgraph thread or
- * deadlock will occur when reconfiguration happens.
+ * N.B. lock() and unlock() cannot be called from a flowgraph thread
+ * (E.g., gr_block::work method) or deadlock will occur when
+ * reconfiguration happens.
*/
virtual void unlock();
};
Modified: gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
===================================================================
--- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
2007-08-29 00:30:52 UTC (rev 6200)
+++ gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
2007-08-29 00:42:11 UTC (rev 6201)
@@ -32,15 +32,19 @@
#include <stdexcept>
#include <iostream>
+#include <string.h>
#define GR_TOP_BLOCK_IMPL_DEBUG 0
static gr_top_block_impl *s_impl = 0;
-// Make a vector of gr_block from a vector of gr_basic_block
-static
-gr_block_vector_t
-make_gr_block_vector(gr_basic_block_vector_t &blocks)
+/*!
+ * Make a vector of gr_block from a vector of gr_basic_block
+ *
+ * Pass-by-value to avoid problem with possible asynchronous modification
+ */
+static gr_block_vector_t
+make_gr_block_vector(gr_basic_block_vector_t blocks)
{
gr_block_vector_t result;
for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
@@ -51,22 +55,30 @@
}
// FIXME: This prevents using more than one gr_top_block instance
+
static void
runtime_sigint_handler(int signum)
{
- if (GR_TOP_BLOCK_IMPL_DEBUG)
- std::cout << "SIGINT received, calling stop()" << std::endl;
+ if (GR_TOP_BLOCK_IMPL_DEBUG){
+ char *msg = "SIGINT received, calling stop()\n";
+ ::write(1, msg, strlen(msg)); // write is OK to call from signal
handler
+ }
if (s_impl)
s_impl->stop();
}
+// ----------------------------------------------------------------
+
gr_top_block_impl::gr_top_block_impl(gr_top_block *owner)
: d_running(false),
d_ffg(),
d_owner(owner),
d_lock_count(0)
{
+ if (s_impl)
+ throw std::logic_error("gr_top_block_impl: multiple simultaneous
gr_top_block's");
+
s_impl = this;
}
@@ -115,18 +127,22 @@
d_running = true;
}
+/*
+ * N.B. as currently implemented, it is possible that this may be
+ * invoked by the SIGINT handler which is fragile as hell...
+ */
void
gr_top_block_impl::stop()
{
- if (GR_TOP_BLOCK_IMPL_DEBUG)
- std::cout << "stop: entered" << std::endl;
+ if (GR_TOP_BLOCK_IMPL_DEBUG){
+ char *msg = "stop: entered\n";
+ ::write(1, msg, strlen(msg));
+ }
for (gr_scheduler_thread_viter_t p = d_threads.begin(); p !=
d_threads.end(); p++) {
- if (GR_TOP_BLOCK_IMPL_DEBUG)
- std::cout << "stop: stopping thread " << (*p) << std::endl;
- (*p)->stop();
+ if (*p)
+ (*p)->stop();
}
-
d_running = false;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r6201 - in gnuradio/trunk: . gnuradio-core/src/lib/runtime,
eb <=