[rkward-cvs] SF.net SVN: rkward:[3178] branches/2010_10_18_backend_restructuring_branch/ rkward/rbackend
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Thu Nov 4 16:26:26 UTC 2010
Revision: 3178
http://rkward.svn.sourceforge.net/rkward/?rev=3178&view=rev
Author: tfry
Date: 2010-11-04 16:26:26 +0000 (Thu, 04 Nov 2010)
Log Message:
-----------
Some tweaking, and rework exit strategy.
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/rinterface.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
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-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp 2010-11-04 16:26:26 UTC (rev 3178)
@@ -111,15 +111,6 @@
SEXP runCommandInternalBase (SEXP pr, RThread::RKWardRError *error);
// ############## R Standard callback overrides BEGIN ####################
-void RSuicide (const char* message) {
- RK_TRACE (RBACKEND);
-
- RBackendRequest request (true, RBackendRequest::BackendExit);
- request.params["message"] = QVariant (i18n ("The R engine has encountered a fatal error:\n%1").arg (message));
- RThread::this_pointer->handleRequest (&request);
- RThread::this_pointer->killed = true;
-}
-
Rboolean RKToplevelStatementFinishedCallback (SEXP expr, SEXP value, Rboolean succeeded, Rboolean visible, void *) {
RK_TRACE (RBACKEND);
Q_UNUSED (expr);
@@ -319,7 +310,7 @@
RK_TRACE (RBACKEND);
// output while nothing else is running (including handlers?) -> This may be a syntax error.
- if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->killed)) {
+ if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->isKilled ())) {
if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandTransmitted) {
// status UserCommandTransmitted might have been set from RKToplevelStatementFinishedHandler, too, in which case all is fine
// (we're probably inside another task handler at this point, then)
@@ -345,6 +336,14 @@
void RCleanUp (SA_TYPE saveact, int status, int RunLast) {
RK_TRACE (RBACKEND);
+ if (RThread::this_pointer->killed == RThread::AlreadyDead) return; // Nothing to clean up
+
+ // we could be in a signal handler, and the stack base may have changed.
+ uintptr_t old_lim = R_CStackLimit;
+ R_CStackLimit = (uintptr_t)-1;
+
+ if ((status != 0) && (RThread::this_pointer->killed != RThread::ExitNow)) RThread::this_pointer->killed = RThread::EmergencySaveThenExit;
+
if (saveact != SA_SUICIDE) {
if (!RThread::this_pointer->isKilled ()) {
RBackendRequest request (true, RBackendRequest::BackendExit);
@@ -357,17 +356,56 @@
R_RunExitFinalizers ();
R_CleanTempDir ();
}
- RThread::this_pointer->killed = true; // just in case
+
+ RThread::this_pointer->r_running = false; // To signify we have finished everything else and are now trying to create an emergency save (if applicable)
+
+ if (RThread::this_pointer->killed == RThread::EmergencySaveThenExit) {
+ if (R_DirtyImage) R_SaveGlobalEnvToFile (RKCommonFunctions::getUseableRKWardSavefileName ("rkward_recover", ".RData").toLocal8Bit ());
+ }
+
+ RThread::this_pointer->killed = RThread::AlreadyDead; // just in case
+
+ R_CStackLimit = old_lim; // well, it should not matter any longer, but...
}
+void RSuicide (const char* message) {
+ RK_TRACE (RBACKEND);
+
+ if (!RThread::this_pointer->isKilled ()) {
+ RBackendRequest request (true, RBackendRequest::BackendExit);
+ request.params["message"] = QVariant (i18n ("The R engine has encountered a fatal error:\n%1").arg (message));
+ RThread::this_pointer->handleRequest (&request);
+ RThread::this_pointer->killed = RThread::EmergencySaveThenExit;
+ RCleanUp (SA_SUICIDE, 1, 0);
+ } else {
+ RK_ASSERT (false);
+ }
+}
+
void RThread::tryToDoEmergencySave () {
RK_TRACE (RBACKEND);
- // we're probably in a signal handler, and the stack base has changed.
- uintptr_t old_lim = R_CStackLimit;
- R_CStackLimit = (uintptr_t)-1;
- if (R_DirtyImage) R_SaveGlobalEnvToFile (RKCommonFunctions::getUseableRKWardSavefileName ("rkward_recover", ".RData").toLocal8Bit ());
- R_CStackLimit = old_lim;
+ if (inRThread ()) {
+ // If we are in the correct thread, things are easy:
+ RCleanUp (SA_SUICIDE, 1, 0);
+ RK_doIntr (); // to jump out of the loop, if needed
+ } else {
+ // If we are in the wrong thread, things are a lot more tricky. We need to cause the R thread to exit, and wait for it to finish saving.
+ // Fortunately, if we are in the wrong thread, that probably means, the R thread did *not* crash, and will thus still be functional
+ this_pointer->killed = EmergencySaveThenExit;
+ this_pointer->interruptProcessing (true);
+ for (int i = 0; i < 100; ++i) { // give it up to ten seconds to intterrupt and exit the loop
+ if (!this_pointer->r_running) break;
+ msleep (100);
+ }
+ if (!this_pointer->r_running) {
+ for (int i = 0; i < 600; ++i) { // give it up to sixty seconds to finish saving
+ if (this_pointer->killed == AlreadyDead) return; // finished
+ msleep (100);
+ }
+ }
+ RK_ASSERT (false); // Too bad, but we seem to be stuck. No chance but to return (and crash)
+ }
}
QStringList charPArrayToQStringList (const char** chars, int count) {
@@ -651,6 +689,7 @@
void RThread::processX11Events () {
// do not trace
if (!this_pointer->r_running) return;
+ if (this_pointer->isKilled ()) return;
RThread::repl_status.eval_depth++;
// In case an error (or user interrupt) is caught inside processX11EventsWorker, we don't want to long-jump out.
@@ -662,7 +701,7 @@
SEXP doError (SEXP call) {
RK_TRACE (RBACKEND);
- if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->killed)) {
+ if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->isKilled ())) {
RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandFailed;
}
if (RThread::repl_status.interrupted) {
@@ -965,7 +1004,7 @@
if (ctype & RCommand::DirectToOutput) runDirectCommand (".rk.capture.messages()");
if (ctype & RCommand::QuitCommand) {
- killed = true;
+ killed = ExitNow;
} else if (!(ctype & RCommand::EmptyCommand)) {
repl_status.eval_depth++;
SEXP parsed = parseCommand (command->command, &error);
@@ -991,9 +1030,6 @@
}
if (ctype & RCommand::DirectToOutput) runDirectCommand (".rk.print.captured.messages()");
- if (!(ctype & RCommand::Internal)) {
- if (!RInterface::backendIsLocked () || killed) processX11Events ();
- }
// common error/status handling
if (error != NoError) {
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h 2010-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h 2010-11-04 16:26:26 UTC (rev 3178)
@@ -197,9 +197,16 @@
return (r_version >= (1000 * major + 10 * minor + revision));
}
+/** thread is killed. Should exit as soon as possible. @see kill */
+ enum KillType {
+ NotKilled = 0,
+ ExitNow = 1,
+ EmergencySaveThenExit = 2,
+ AlreadyDead = 3
+ } killed;
/** "Kills" the thread. Actually this just tells the thread that is is about to be terminated. Allows the thread to terminate gracefully */
- void kill () { killed = true; };
- bool isKilled () { return killed; };
+ void kill () { killed = ExitNow; };
+ bool isKilled () { return (killed != NotKilled); };
QTextCodec *current_locale_codec;
@@ -226,8 +233,6 @@
static void *default_global_context;
void commandFinished (bool check_object_updates_needed=true);
-/** thread is killed. Should exit as soon as possible. @see kill */
- bool killed;
/** A list of symbols that have been assigned new values during the current command */
QStringList changed_symbol_names;
static bool inRThread () { return (currentThread () == this_pointer); };
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp 2010-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp 2010-11-04 16:26:26 UTC (rev 3178)
@@ -137,19 +137,6 @@
return (idle);
}
-bool RInterface::backendIsLocked () {
- return (RKGlobals::rInterface ()->locked != 0);
-}
-
-void RInterface::tryToDoEmergencySave () {
- RK_TRACE (RBACKEND);
- if (!RThread::inRThread ()) {
- RKGlobals::rInterface ()->r_thread->terminate ();
- RKGlobals::rInterface ()->r_thread->wait (1000);
- }
- RKGlobals::rInterface ()->r_thread->tryToDoEmergencySave ();
-}
-
void RInterface::startThread () {
RK_TRACE (RBACKEND);
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h 2010-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h 2010-11-04 16:26:26 UTC (rev 3178)
@@ -19,7 +19,6 @@
#define RINTERFACE_H
#include <qobject.h>
-#include <qmutex.h>
#include <QFile>
#include "rcommand.h"
@@ -29,7 +28,6 @@
class RKWardMainWindow;
class QTimer;
class RThread;
-struct RKWardStartupOptions;
struct RBackendRequest;
/** This class provides the main interface to the R-processor.
@@ -74,10 +72,6 @@
bool backendIsDead ();
bool backendIsIdle ();
-
- static bool backendIsLocked ();
-
- static void tryToDoEmergencySave ();
private slots:
/** called periodically to flush output buffer in RThread */
void flushOutput ();
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp 2010-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp 2010-11-04 16:26:26 UTC (rev 3178)
@@ -20,7 +20,6 @@
#include <signal.h>
#include "rembedinternal.h"
-#include "rinterface.h"
#include "../debug.h"
@@ -70,7 +69,7 @@
RK_ASSERT (signum == SIGSEGV);
}
- RInterface::tryToDoEmergencySave ();
+ RThread::tryToDoEmergencySave ();
// if we are not in the R thread, handling the signal in R does more harm than good.
if (RThread::inRThread ()) {
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp 2010-11-03 18:54:06 UTC (rev 3177)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp 2010-11-04 16:26:26 UTC (rev 3178)
@@ -45,7 +45,7 @@
void RThread::run () {
RK_TRACE (RBACKEND);
thread_id = currentThreadId ();
- killed = false;
+ killed = NotKilled;
previous_command = 0;
initialize ();
@@ -91,7 +91,7 @@
if (killed) return 0;
// NOTE: processX11Events() may, conceivably, lead to new requests, which may also wait for sub-commands!
processX11Events ();
- if (!request->done) msleep (10);
+ if (!request->done) msleep (1);
}
RCommandProxy* command = request->command;
@@ -125,6 +125,7 @@
void RThread::waitIfOutputBufferExceeded () {
// don't trace
while (out_buf_len > MAX_BUF_LENGTH) {
+ if (isKilled ()) return; // don't block. Frontend could be crashed
msleep (10);
}
}
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