[rkward-cvs] SF.net SVN: rkward:[3879] trunk/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Tue Oct 4 14:34:23 UTC 2011


Revision: 3879
          http://rkward.svn.sourceforge.net/rkward/?rev=3879&view=rev
Author:   tfry
Date:     2011-10-04 14:34:22 +0000 (Tue, 04 Oct 2011)
Log Message:
-----------
Make an effort to support fork()ing

Modified Paths:
--------------
    trunk/rkward/ChangeLog
    trunk/rkward/rkward/rbackend/rinterface.cpp
    trunk/rkward/rkward/rbackend/rkrbackend.cpp
    trunk/rkward/rkward/rbackend/rkrbackend.h
    trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.h

Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog	2011-10-03 20:41:59 UTC (rev 3878)
+++ trunk/rkward/ChangeLog	2011-10-04 14:34:22 UTC (rev 3879)
@@ -1,3 +1,5 @@
+--- Version 0.5.7 - Oct-XX-2011
+- Fix problems with using mclapply() inside RKWard
 - Offer to add a new library location, automatically, if location selected for installation is not writable
 - Reworked package installation / update dialog
 - Fixed: Integrated help browser would not update navigation history when following page internal links

Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp	2011-10-03 20:41:59 UTC (rev 3878)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp	2011-10-04 14:34:22 UTC (rev 3879)
@@ -513,6 +513,9 @@
 	} else if (call == "preLocaleChange") {
 		int res = KMessageBox::warningContinueCancel (0, i18n ("A command in the R backend is trying to change the character encoding. While RKWard offers support for this, and will try to adjust to the new locale, this operation may cause subtle bugs, if data windows are currently open. Also the feature is not well tested, yet, and it may be advisable to save your workspace before proceeding.\nIf you have any data editor opened, or in any doubt, it is recommended to close those first (this will probably be auto-detected in later versions of RKWard). In this case, please chose 'Cancel' now, then close the data windows, save, and retry."), i18n ("Locale change"));
 		if (res != KMessageBox::Continue) return (QStringList ("FALSE"));
+	} else if (call == "forkNotification") {
+		KMessageBox::information (0, i18n ("<p>A command running in the R backend has caused the R backend process to \"fork\". Typically this is done to spread computations onto several CPU cores. We try our best to support this in RKWard, despite some technical problems inherent in forking a multi-library, multi-threaded application. However, it is entirely possible that this causes trouble / broken features in some cases, particularly in combination with further R libraries. If you observe any such adverse effects after forking, please send us a bug report.</p>"
+		"<p>If you have a choice, consider using a different technique of parallelization, e.g. the 'PSOCK' method of R packages <i>snow</i> or <i>parallel</i>.</p>"), i18n ("Backend has forked"), "fork_notification");
 	} else if (call == "listPlugins") {
 		RK_ASSERT (calllist.count () == 1);
 		return RKComponentMap::getMap ()->allComponentIds ();

Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-10-03 20:41:59 UTC (rev 3878)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-10-04 14:34:22 UTC (rev 3879)
@@ -694,7 +694,8 @@
 
 // ############## R Standard callback overrides END ####################
 
-RKRBackend::RKRBackend () {
+// NOTE: stdout_stderr_mutex is recursive to support fork()s, better
+RKRBackend::RKRBackend () : stdout_stderr_mutex (QMutex::Recursive) {
 	RK_TRACE (RBACKEND);
 
 	current_locale_codec = QTextCodec::codecForLocale ();
@@ -1035,9 +1036,45 @@
 	return true;
 }
 
+#ifndef Q_OS_WIN
+static bool backend_was_forked = false;
+void prepareFork () {
+	if (!RKRBackendProtocolBackend::inRThread ()) return;
+
+	// we need to make sure that the transmitter thread does not hold a lock on the mutex!
+	RKRBackend::this_pointer->stdout_stderr_mutex.lock ();
+}
+
+void completeForkMaster () {
+	if (!RKRBackendProtocolBackend::inRThread ()) return;
+
+	RKRBackend::this_pointer->stdout_stderr_mutex.unlock ();
+
+	if (backend_was_forked) return;
+	backend_was_forked = true;
+
+	// Block SIGCLD in the main thread from now on. I don't fully understand, why, but otherwise, these signals
+	// interrupt the select() call in the fork()ing code of library(parallel)
+	sigset_t new_set;
+	sigemptyset (&new_set);
+	sigaddset (&new_set, SIGCLD);
+	pthread_sigmask (SIG_BLOCK, &new_set, NULL);
+
+	RKRBackend::this_pointer->handlePlainGenericRequest (QStringList ("forkNotification"), false);
+}
+
+void completeForkChild () {
+	RKRBackendProtocolBackend::instance ()->r_thread_id = QThread::currentThreadId();
+}
+#endif
+
 void RKRBackend::enterEventLoop () {
 	RK_TRACE (RBACKEND);
 
+#ifndef Q_OS_WIN
+	pthread_atfork (prepareFork, completeForkMaster, completeForkChild);
+#endif
+
 	run_Rmainloop ();
 	// NOTE: Do NOT run Rf_endEmbeddedR(). It does more that we want. We rely on RCleanup, instead.
 }

Modified: trunk/rkward/rkward/rbackend/rkrbackend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.h	2011-10-03 20:41:59 UTC (rev 3878)
+++ trunk/rkward/rkward/rbackend/rkrbackend.h	2011-10-04 14:34:22 UTC (rev 3879)
@@ -188,12 +188,13 @@
  *  @param forcibly: if false, and the other thread currently has a lock on the mutex, do nothing, and return false.
  *  @returns: true, if output was actually fetched (or no output was available), false, if the function gave up on a locked mutex. */
 	bool fetchStdoutStderr (bool forcibly);
+/** public for technical reasons */
+	QMutex stdout_stderr_mutex;
 private:
 	void clearPendingInterrupt ();
 protected:
 	RCommandProxy* handleRequest (RBackendRequest *request, bool mayHandleSubstack);
 private:
-	QMutex stdout_stderr_mutex;
 	int stdout_stderr_fd;
 /** set up R standard callbacks */
 	void setupCallbacks ();

Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.h	2011-10-03 20:41:59 UTC (rev 3878)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_backend.h	2011-10-04 14:34:22 UTC (rev 3879)
@@ -43,6 +43,7 @@
 	static RKRBackendProtocolBackend* _instance;
 	QThread *r_thread;
 #ifndef Q_WS_WIN
+	friend void completeForkChild ();
 	Qt::HANDLE r_thread_id;
 #endif
 };

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.





More information about the rkward-tracker mailing list