Our ForkedcallsController class currently uses a Timeout variable to 
initiate checks for any completed child processes every 100ms. This 
is conceptually ugly, as it requires us to use the GUI libraries and 
will prevent forked calls working correctly when the GUI event loop 
is not started. (Ie, lyx --export). That isn't a problem now, but it 
might become one in the future. And anyway it's ugly.

Attached is a patch to use the SIGCHLD signal instead of this Timeout. The 
patch is against the 13x tree which is what I have available here at 
work. (I'm not proposing adding this patch to LyX 13x.) As 
proof-of-concept, it seems to work perfectly.

This is my first go at using the SIGFOO family, so I'd value it if 
someone more knowledgable took a look. Specifically, will this code 
work if a SIGCHLD signal is received whilst we're still processing a 
previous SIGCHLD signal in ForkedcallsController::timer()?

static void child_handler(int err_sig)
{
        switch (err_sig) {
        case SIGCHLD:
                lyxerr << "\nlyx: SIGCHLD signal caught" << endl;
                ForkedcallsController::get().timer();
                break;
        default:
                lyxerr << "\nlyx: warning! Unexpected signal caught!"
                       << err_sig << endl;
        }
}

void LyX::init(bool gui)
{
        signal(SIGCHLD, child_handler);
        ...
}

Or should the code in child_handler be truly trivial:

static bool sigchild_received = false;

static void child_handler(int err_sig)
{
        switch (err_sig) {
        case SIGCHLD:
                sigchild_received = true;
                break;
        default:
                lyxerr << "\nlyx: warning! Unexpected signal caught!"
                       << err_sig << endl;
        }
}

Leaving the handling of sigchild_received to someplace outside of the 
handler?

Angus
? build-qt
? build-xforms
? sigchld.diff
Index: src/lyx_main.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyx_main.C,v
retrieving revision 1.134.2.2
diff -u -p -r1.134.2.2 lyx_main.C
--- src/lyx_main.C	12 Feb 2004 17:18:02 -0000	1.134.2.2
+++ src/lyx_main.C	19 Mar 2004 17:49:08 -0000
@@ -16,6 +16,7 @@
 #include "lyx_main.h"
 
 #include "support/filetools.h"
+#include "support/forkedcontr.h"
 #include "support/lyxlib.h"
 #include "support/os.h"
 #include "support/FileInfo.h"
@@ -169,6 +170,19 @@ LyX::LyX(int & argc, char * argv[])
 
 extern "C" {
 
+static void child_handler(int err_sig)
+{
+	switch (err_sig) {
+	case SIGCHLD:
+		lyxerr << "\nlyx: SIGCHLD signal caught" << endl;
+		ForkedcallsController::get().timer();
+		break;
+	default:
+		lyxerr << "\nlyx: warning! Unexpected signal caught!"
+		       << err_sig << endl;
+	}
+}
+
 static void error_handler(int err_sig)
 {
 	switch (err_sig) {
@@ -195,6 +209,7 @@ static void error_handler(int err_sig)
 	}
 
 	// Deinstall the signal handlers
+	signal(SIGCHLD, SIG_DFL);
 	signal(SIGHUP, SIG_DFL);
 	signal(SIGINT, SIG_DFL);
 	signal(SIGFPE, SIG_DFL);
@@ -215,6 +230,7 @@ static void error_handler(int err_sig)
 
 void LyX::init(bool gui)
 {
+	signal(SIGCHLD, child_handler);
 	signal(SIGHUP, error_handler);
 	signal(SIGFPE, error_handler);
 	signal(SIGSEGV, error_handler);
Index: src/support/forkedcontr.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/forkedcontr.C,v
retrieving revision 1.6.2.2
diff -u -p -r1.6.2.2 forkedcontr.C
--- src/support/forkedcontr.C	7 Mar 2003 15:43:58 -0000	1.6.2.2
+++ src/support/forkedcontr.C	19 Mar 2004 17:49:09 -0000
@@ -50,10 +50,12 @@ ForkedcallsController & ForkedcallsContr
 
 ForkedcallsController::ForkedcallsController()
 {
+#if 0
 	timeout_ = new Timeout(100, Timeout::ONETIME);
 
 	timeout_->timeout
 		.connect(boost::bind(&ForkedcallsController::timer, this));
+#endif
 }
 
 
@@ -67,14 +69,18 @@ ForkedcallsController::~ForkedcallsContr
 		delete *it;
 	}
 
+#if 0
 	delete timeout_;
+#endif
 }
 
 
 void ForkedcallsController::addCall(ForkedProcess const & newcall)
 {
+#if 0
 	if (!timeout_->running())
 		timeout_->start();
+#endif
 
 	forkedCalls.push_back(newcall.clone());
 	childrenChanged();
@@ -85,6 +91,7 @@ void ForkedcallsController::addCall(Fork
 // Check the list and, if there is a stopped child, emit the signal.
 void ForkedcallsController::timer()
 {
+	lyxerr << "Entered ForkedcallsController::timer()" << endl;
 	ListType::size_type start_size = forkedCalls.size();
 
 	ListType::iterator it  = forkedCalls.begin();
@@ -148,12 +155,15 @@ void ForkedcallsController::timer()
 		}
 	}
 
+#if 0
 	if (!forkedCalls.empty() && !timeout_->running()) {
 		timeout_->start();
 	}
+#endif
 
 	if (start_size != forkedCalls.size())
 		childrenChanged();
+	lyxerr << "Leaving ForkedcallsController::timer()" << endl;
 }
 
 
@@ -206,7 +216,9 @@ void ForkedcallsController::kill(pid_t p
 	(*it)->kill(tolerance);
 	forkedCalls.erase(it);
 
+#if 0
 	if (forkedCalls.empty()) {
 		timeout_->stop();
 	}
+#endif
 }

Reply via email to