[rkward-cvs] SF.net SVN: rkward:[3164] branches/2010_10_18_backend_restructuring_branch/ rkward/rbackend

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sat Oct 30 11:01:19 UTC 2010


Revision: 3164
          http://rkward.svn.sourceforge.net/rkward/?rev=3164&view=rev
Author:   tfry
Date:     2010-10-30 11:01:19 +0000 (Sat, 30 Oct 2010)

Log Message:
-----------
Correctly detect interrupted commands

Modified Paths:
--------------
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.h
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-28 19:32:08 UTC (rev 3163)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-30 11:01:19 UTC (rev 3164)
@@ -19,7 +19,7 @@
 
 // static
 RThread *RThread::this_pointer = 0;
-RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0, false };
+RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0, false, false };
 void* RThread::default_global_context = 0;
 
 #include <qstring.h>
@@ -75,26 +75,26 @@
 #include <Rinternals.h>
 #include <R_ext/Parse.h>
 #include <Rembedded.h>
+#include <Rinterface.h>
 
 #ifdef Q_WS_WIN
 #	include <R_ext/RStartup.h>
 #	include <R_ext/Utils.h>
 
-	void RK_scheduleIntr () {
-		UserBreak = 1;
-	}
-
-	void RK_doIntr () {
-		RK_scheduleIntr ();
-		R_CheckUserInterrupt ();
-	}
-
 	structRstart RK_R_Params;
-#else
-#	define RK_doIntr Rf_onintr
-#	include <Rinterface.h>
 #endif
 
+void RK_scheduleIntr () {
+	RThread::this_pointer->repl_status.interrupted = true;
+	RKSignalSupport::callOldSigIntHandler ();
+}
+
+void RK_doIntr () {
+	RK_scheduleIntr ();
+	RThread::this_pointer->repl_status.interrupted = true;
+	R_CheckUserInterrupt ();
+}
+
 // some functions we need that are not declared
 extern void Rf_PrintWarnings (void);
 extern void run_Rmainloop (void);
@@ -671,15 +671,26 @@
 	RThread::repl_status.eval_depth--;
 }
 
+extern int R_interrupts_pending;
 SEXP doError (SEXP call) {
 	RK_TRACE (RBACKEND);
 
 	if ((RThread::this_pointer->repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->killed)) {
 		RThread::this_pointer->repl_status.user_command_status = RThread::RKReplStatus::UserCommandFailed;
 	}
-	QString string = RKRSupport::SEXPToString (call);
-	RThread::this_pointer->handleOutput (string, string.length (), ROutput::Error);
-	RK_DO (qDebug ("error '%s'", qPrintable (string)), RBACKEND, DL_DEBUG);
+	if (RThread::this_pointer->repl_status.interrupted) {
+		// it is unlikely, but possible, that an interrupt signal was received, but the current command failed for some other reason, before processing was acutally interrupted. In this case, R_interrupts_pending if not yet cleared.
+		// NOTE: if R_interrupts_pending stops being exported one day, we might be able to use R_CheckUserInterrupt() inside an R_ToplevelExec() to find out, whether an interrupt was still pending.
+		if (!R_interrupts_pending) {
+			RThread::this_pointer->repl_status.interrupted = false;
+			foreach (RCommandProxy *command, RThread::this_pointer->all_current_commands) command->status |= RCommand::Canceled;
+			RK_DO (qDebug ("interrupted"), RBACKEND, DL_DEBUG);
+		}
+	} else {
+		QString string = RKRSupport::SEXPToString (call);
+		RThread::this_pointer->handleOutput (string, string.length (), ROutput::Error);
+		RK_DO (qDebug ("error '%s'", qPrintable (string)), RBACKEND, DL_DEBUG);
+	}
 	return R_NilValue;
 }
 
@@ -822,7 +833,8 @@
 	RKWard_RData_Tag = Rf_install ("RKWard_RData_Tag");
 	R_LastvalueSymbol = Rf_install (".Last.value");
 
-	RKSignalSupport::installSignalProxies ();
+	RKSignalSupport::installSignalProxies ();	// for the crash signals
+	RKSignalSupport::installSigIntAndUsrHandlers (RK_scheduleIntr);
 
 // register our functions
 	R_CallMethodDef callMethods [] = {

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-28 19:32:08 UTC (rev 3163)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-30 11:01:19 UTC (rev 3164)
@@ -195,6 +195,7 @@
 
 /** The command currently being executed. */
 	RCommandProxy *current_command;
+	QList<RCommandProxy*> all_current_commands;
 
 	void runCommand (RCommandProxy *command);
 
@@ -230,6 +231,7 @@
 		} user_command_status;
 		int eval_depth;		// Number (depth) of non-user commands currently running. User commands can only run at depth 0
 		bool in_browser_context;
+		bool interrupted;
 	};
 	static RKReplStatus repl_status;
 /** holds a copy of the default R_GlobalContext. Needed to find out, when a browser context has been left. */
@@ -263,7 +265,6 @@
 	QStringList global_env_toplevel_names;
 /** check wether the object list / global environment / individual symbols have changed, and updates them, if needed */
 	void checkObjectUpdatesNeeded (bool check_list);
-	QList<RCommandProxy*> all_current_commands;
 
 	/** current output */
 	ROutputList output_buffer;

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp	2010-10-28 19:32:08 UTC (rev 3163)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp	2010-10-30 11:01:19 UTC (rev 3164)
@@ -23,10 +23,8 @@
 
 #include "../debug.h"
 
-#ifdef Q_WS_WIN
-#	ifndef __sighandler_t
-		typedef void (*__sighandler_t) (int);
-#	endif
+#ifndef __sighandler_t
+	typedef void (*__sighandler_t) (int);
 #endif
 
 namespace RKSignalSupportPrivate {
@@ -45,6 +43,12 @@
 	struct sigaction r_sigabrt_handler;
 	struct sigaction default_sigabrt_handler;
 #endif
+	__sighandler_t r_sigint_handler = 0;
+	void (*new_sigint_handler) (void) = 0;
+	void internal_sigint_handler (int num) {
+		new_sigint_handler ();
+		signal (num, internal_sigint_handler);
+	}
 
 #ifdef Q_WS_WIN
 	void signal_proxy (int signum) {
@@ -153,3 +157,20 @@
 	sigaction (SIGABRT, &proxy_action, 0);
 #endif
 }
+
+void RKSignalSupport::installSigIntAndUsrHandlers (void (*handler) (void)) {
+	RK_TRACE (RBACKEND);
+
+	RK_ASSERT (!RKSignalSupportPrivate::r_sigint_handler);
+	RKSignalSupportPrivate::new_sigint_handler = handler;
+	RKSignalSupportPrivate::r_sigint_handler = signal (SIGINT, &RKSignalSupportPrivate::internal_sigint_handler);
+	// default action in R: save and quit. We use these as a proxy for SIGINT, instead.
+	signal (SIGUSR1, &RKSignalSupportPrivate::internal_sigint_handler);
+	signal (SIGUSR2, &RKSignalSupportPrivate::internal_sigint_handler);
+}
+
+void RKSignalSupport::callOldSigIntHandler () {
+	RK_TRACE (RBACKEND);
+
+	RKSignalSupportPrivate::r_sigint_handler (SIGINT);
+}

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.h	2010-10-28 19:32:08 UTC (rev 3163)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.h	2010-10-30 11:01:19 UTC (rev 3164)
@@ -21,6 +21,9 @@
 namespace RKSignalSupport {
 	void saveDefaultSignalHandlers ();
 	void installSignalProxies ();
+
+	void installSigIntAndUsrHandlers (void (*handler) (void));
+	void callOldSigIntHandler ();
 };
 
 #endif

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp	2010-10-28 19:32:08 UTC (rev 3163)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp	2010-10-30 11:01:19 UTC (rev 3164)
@@ -48,7 +48,7 @@
 #ifdef Q_WS_WIN
 	RK_scheduleIntr ();
 #else
-	pthread_kill ((pthread_t) thread_id, SIGINT);
+	pthread_kill ((pthread_t) thread_id, SIGUSR1);	// relays to SIGINT
 #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