The xforms event loop in my tree now looks like:
while (!finished) {
ForkedcallsController::get().handleCompletedProcesses();
if (fl_check_forms() == FL_EVENT) {
...
}
}
where handleCompletedProcesses() simply checks whether a SIGCHLD
signal has been received and, if so, cleans up after it.
(handle_children is set to true in the handler receiving a SIGCHLD
signal.)
void ForkedcallsController::handleCompletedProcesses()
{
// The loop ensures that we handle any signals that are
// received whilst we're processing an existing signal.
while (handle_children) {
handle_children = false;
wait(); // The old ForkedcallsController::timer() function.
}
}
Questions:
1. Is this the right way to go?
2. How do I do this for Qt, given that the xforms event loop above is
replaced with
qApp->exec();
????
--
Angus
? src/frontends/controllers/TODO
? src/frontends/xforms/1.4-XFormsView.C
? src/frontends/xforms/1.4-XWorkArea.C
? src/frontends/xforms/1.4-XWorkArea.h
? src/frontends/xforms/1.4-bmtable.c
? src/frontends/xforms/1.4-bmtable.h
? src/support/lyxlib-orig.C
? src/support/lyxlib.C
Index: src/frontends/xforms/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/lyx_gui.C,v
retrieving revision 1.58
diff -u -p -r1.58 lyx_gui.C
--- src/frontends/xforms/lyx_gui.C 14 Dec 2003 16:33:56 -0000 1.58
+++ src/frontends/xforms/lyx_gui.C 22 Mar 2004 14:43:53 -0000
@@ -34,6 +34,7 @@
#include "graphics/LoaderQueue.h"
#include "support/filetools.h"
+#include "support/forkedcontr.h"
#include "support/lyxlib.h"
#include "support/os.h"
#include "support/path_defines.h"
@@ -48,6 +49,7 @@
using lyx::support::AddName;
using lyx::support::user_lyxdir;
+using lyx::support::ForkedcallsController;
namespace os = lyx::support::os;
@@ -308,6 +310,7 @@ void start(string const & batch, vector<
// enter the event loop
while (!finished) {
+ ForkedcallsController::get().handleCompletedProcesses();
if (fl_check_forms() == FL_EVENT) {
XEvent ev;
fl_XNextEvent(&ev);
Index: src/support/forkedcontr.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/forkedcontr.C,v
retrieving revision 1.18
diff -u -p -r1.18 forkedcontr.C
--- src/support/forkedcontr.C 22 Mar 2004 14:10:20 -0000 1.18
+++ src/support/forkedcontr.C 22 Mar 2004 14:43:53 -0000
@@ -17,25 +17,22 @@
#include "forkedcontr.h"
#include "forkedcall.h"
#include "lyxfunctional.h"
-#include "debug.h"
-
-#include "frontends/Timeout.h"
-#include <boost/bind.hpp>
+#include "debug.h"
#include <cerrno>
+#include <csignal>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
-using boost::bind;
-
using std::endl;
using std::find_if;
using std::string;
#ifndef CXX_GLOBAL_CSTD
+using std::signal;
using std::strerror;
#endif
@@ -43,6 +40,18 @@ using std::strerror;
namespace lyx {
namespace support {
+namespace {
+
+sig_atomic_t handle_children = false;
+
+extern "C"
+void child_handler(int)
+{
+ handle_children = true;
+}
+
+} // namespace anon
+
// Ensure, that only one controller exists inside process
ForkedcallsController & ForkedcallsController::get()
{
@@ -53,10 +62,7 @@ ForkedcallsController & ForkedcallsContr
ForkedcallsController::ForkedcallsController()
{
- timeout_ = new Timeout(100, Timeout::ONETIME);
-
- timeout_->timeout
- .connect(bind(&ForkedcallsController::timer, this));
+ signal(SIGCHLD, child_handler);
}
@@ -70,22 +76,31 @@ ForkedcallsController::~ForkedcallsContr
delete *it;
}
- delete timeout_;
+ // Deinstall the signal handler
+ signal(SIGCHLD, SIG_DFL);
}
-void ForkedcallsController::addCall(ForkedProcess const & newcall)
+void ForkedcallsController::handleCompletedProcesses()
{
- if (!timeout_->running())
- timeout_->start();
+ // The loop ensures that we handle any signals that are received whilst
+ // we're processing an existing signal.
+ while (handle_children) {
+ handle_children = false;
+ wait();
+ }
+}
+
+void ForkedcallsController::addCall(ForkedProcess const & newcall)
+{
forkedCalls.push_back(newcall.clone().release());
}
// Timer-call
// Check the list and, if there is a stopped child, emit the signal.
-void ForkedcallsController::timer()
+void ForkedcallsController::wait()
{
ListType::iterator it = forkedCalls.begin();
ListType::iterator end = forkedCalls.end();
@@ -147,10 +162,6 @@ void ForkedcallsController::timer()
++it;
}
}
-
- if (!forkedCalls.empty() && !timeout_->running()) {
- timeout_->start();
- }
}
@@ -167,10 +178,6 @@ void ForkedcallsController::kill(pid_t p
(*it)->kill(tolerance);
forkedCalls.erase(it);
-
- if (forkedCalls.empty()) {
- timeout_->stop();
- }
}
} // namespace support
Index: src/support/forkedcontr.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/forkedcontr.h,v
retrieving revision 1.14
diff -u -p -r1.14 forkedcontr.h
--- src/support/forkedcontr.h 22 Mar 2004 14:10:20 -0000 1.14
+++ src/support/forkedcontr.h 22 Mar 2004 14:43:53 -0000
@@ -20,8 +20,6 @@
#include <list>
-class Timeout;
-
namespace lyx {
namespace support {
@@ -32,6 +30,11 @@ public:
/// Get hold of the only controller that can exist inside the process.
static ForkedcallsController & get();
+ /** Invoked from the GUI process loop to handle any child processes
+ * that have been signaled as completed.
+ */
+ void handleCompletedProcesses();
+
/// Add a new child process to the list of controlled processes.
void addCall(ForkedProcess const &);
@@ -46,22 +49,16 @@ private:
ForkedcallsController(ForkedcallsController const &);
~ForkedcallsController();
- /** This method is connected to the timer. Every XX ms it is called
- * so that we can check on the status of the children. Those that
- * are found to have finished are removed from the list and their
- * callback function is passed the final return state.
+ /** Those child processes that are found to have finished are removed
+ * from the list and their callback function is passed the final
+ * return state.
*/
- void timer();
+ void wait();
/// The child processes
typedef std::list<ForkedProcess *> ListType;
///
ListType forkedCalls;
-
- /** The timer. Enables us to check the status of the children
- * every XX ms and to invoke a callback on completion.
- */
- Timeout * timeout_;
};
} // namespace support