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

tfry at users.sourceforge.net tfry at users.sourceforge.net
Thu Apr 7 08:32:33 UTC 2011


Revision: 3509
          http://rkward.svn.sourceforge.net/rkward/?rev=3509&view=rev
Author:   tfry
Date:     2011-04-07 08:32:33 +0000 (Thu, 07 Apr 2011)

Log Message:
-----------
Better thread safety, and one leak less, while cancelling commands.

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

Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-04-06 17:19:05 UTC (rev 3508)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp	2011-04-07 08:32:33 UTC (rev 3509)
@@ -130,8 +130,10 @@
 
 	if (all_current_commands.isEmpty ()) return;
 	if ((command_id == -1) || (all_current_commands.last ()->id == command_id)) {
-		RK_DO (qDebug ("scheduling interrupt for command id %d", command_id), RBACKEND, DL_DEBUG);
-		scheduleInterrupt ();
+		if (!too_late_to_interrupt) {
+			RK_DO (qDebug ("scheduling interrupt for command id %d", command_id), RBACKEND, DL_DEBUG);
+			scheduleInterrupt ();
+		}
 	} else {
 		// if the command to cancel is *not* the topmost command, then do not interrupt, yet.
 		foreach (RCommandProxy *candidate, all_current_commands) {
@@ -145,6 +147,16 @@
 	}
 }
 
+void clearPendingInterrupt_Worker (void *) {
+	R_CheckUserInterrupt ();
+}
+
+void RKRBackend::clearPendingInterrupt () {
+	RK_TRACE (RBACKEND);
+	bool passed = R_ToplevelExec (clearPendingInterrupt_Worker, 0);
+	if (!passed) RK_DO (qDebug ("pending interrupt cleared"), RBACKEND, DL_DEBUG);
+}
+
 // some functions we need that are not declared
 LibExtern void Rf_PrintWarnings (void);
 LibExtern void run_Rmainloop (void);
@@ -900,6 +912,7 @@
 
 	RKSignalSupport::saveDefaultSignalHandlers ();
 
+	too_late_to_interrupt = false;
 	r_running = true;
 	int argc = 3;
 	char* argv[3] = { qstrdup ("--slave"), qstrdup ("--no-save"), qstrdup ("--no-restore") };
@@ -1184,6 +1197,12 @@
 	RK_TRACE (RBACKEND);
 	RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG);
 
+	{
+		QMutexLocker lock (&all_current_commands_mutex);
+		too_late_to_interrupt = true;
+	}
+	clearPendingInterrupt ();	// Mutex must be unlocked for this!
+
 	current_command->status -= (current_command->status & RCommand::Running);
 	current_command->status |= RCommand::WasTried;
 
@@ -1206,6 +1225,7 @@
 		QMutexLocker lock (&all_current_commands_mutex);
 		all_current_commands.pop_back();
 		if (!all_current_commands.isEmpty ()) current_command = all_current_commands.last ();
+		too_late_to_interrupt = false;
 	}
 }
 
@@ -1249,6 +1269,7 @@
 		QMutexLocker lock (&all_current_commands_mutex);
 		if (current_commands_to_cancel.contains (current_command)) {
 			RK_DO (qDebug ("will now interrupt parent command"), RBACKEND, DL_DEBUG);
+			current_commands_to_cancel.removeAll (current_command);
 			scheduleInterrupt ();
 		}
 	}

Modified: trunk/rkward/rkward/rbackend/rkrbackend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.h	2011-04-06 17:19:05 UTC (rev 3508)
+++ trunk/rkward/rkward/rbackend/rkrbackend.h	2011-04-07 08:32:33 UTC (rev 3509)
@@ -176,7 +176,10 @@
 
 	QMutex all_current_commands_mutex;
 	QList<RCommandProxy*> current_commands_to_cancel;
+	bool too_late_to_interrupt;
 	void interruptCommand (int command_id);
+private:
+	void clearPendingInterrupt ();
 protected:
 	RCommandProxy* handleRequest (RBackendRequest *request, bool mayHandleSubstack);
 private:


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