[rkward-cvs] SF.net SVN: rkward:[3112] trunk/rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Thu Oct 7 14:55:20 UTC 2010
Revision: 3112
http://rkward.svn.sourceforge.net/rkward/?rev=3112&view=rev
Author: tfry
Date: 2010-10-07 14:55:19 +0000 (Thu, 07 Oct 2010)
Log Message:
-----------
Try to pass SIGILL and SIGABRT to the proper handlers (in addtion to SIGSEGV). Attempt to save the workspace on crashes.
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/rkward/misc/rkcommonfunctions.cpp
trunk/rkward/rkward/misc/rkcommonfunctions.h
trunk/rkward/rkward/rbackend/rembedinternal.cpp
trunk/rkward/rkward/rbackend/rembedinternal.h
trunk/rkward/rkward/rbackend/rinterface.cpp
trunk/rkward/rkward/rbackend/rinterface.h
trunk/rkward/rkward/rbackend/rksignalsupport.cpp
trunk/rkward/rkward/rbackend/rksignalsupport.h
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/ChangeLog 2010-10-07 14:55:19 UTC (rev 3112)
@@ -1,3 +1,5 @@
+- Attempt to save workspace on crashes TODO: detect recovery-file at startup, and offer to load it.
+- Also try to relay SIGABRT and SIGILL to the proper signal handlers
- Removed the remainder of the PHP scripting backend
- Fixed: Would crash on tcl/tk events in some cases
Modified: trunk/rkward/rkward/misc/rkcommonfunctions.cpp
===================================================================
--- trunk/rkward/rkward/misc/rkcommonfunctions.cpp 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/misc/rkcommonfunctions.cpp 2010-10-07 14:55:19 UTC (rev 3112)
@@ -2,7 +2,7 @@
rkcommonfunctions - description
-------------------
begin : Mon Oct 17 2005
- copyright : (C) 2005, 2006, 2007, 2009 by Thomas Friedrichsmeier
+ copyright : (C) 2005, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -19,11 +19,14 @@
#include <qstringlist.h>
#include <qdom.h>
#include <qregexp.h>
+#include <QDir>
#include <kxmlguiclient.h>
#include <kglobal.h>
#include <kstandarddirs.h>
+#include "../settings/rksettingsmodulegeneral.h"
+
namespace RKCommonFunctions {
void removeNamedElementsRecursive (const QStringList &names, QDomNode &parent) {
QDomNode nchild;
@@ -136,7 +139,19 @@
return (KGlobal::dirs ()->findResourceDir ("data", "rkward/resource.ver") + "rkward/");
}
+ QString getUseableRKWardSavefileName (const QString &prefix, const QString &postfix) {
+ QDir dir (RKSettingsModuleGeneral::filesPath ());
+ int i=0;
+ while (true) {
+ QString candidate = prefix + QString::number (i) + postfix;
+ if (!dir.exists (candidate)) {
+ return dir.filePath (candidate);
+ }
+ i++;
+ }
+ }
+
QString escape (const QString &in) {
QString out;
Modified: trunk/rkward/rkward/misc/rkcommonfunctions.h
===================================================================
--- trunk/rkward/rkward/misc/rkcommonfunctions.h 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/misc/rkcommonfunctions.h 2010-10-07 14:55:19 UTC (rev 3112)
@@ -2,7 +2,7 @@
rkcommonfunctions - description
-------------------
begin : Mon Oct 17 2005
- copyright : (C) 2005, 2006, 2007, 2009 by Thomas Friedrichsmeier
+ copyright : (C) 2005, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -38,7 +38,10 @@
/** Get the base directory where RKWard data files are stored */
QString getRKWardDataDir ();
+/** Get a suitable file name in the RKWard data directory */
+ QString getUseableRKWardSavefileName (const QString &prefix, const QString &postfix);
+
/** given the context line, find what looks like an R symbol */
QString getCurrentSymbol (const QString &context_line, int cursor_pos, bool strict=true);
/** like get current symbol, but merely returns the start and end position of the current symbol */
Modified: trunk/rkward/rkward/rbackend/rembedinternal.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.cpp 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rembedinternal.cpp 2010-10-07 14:55:19 UTC (rev 3112)
@@ -24,12 +24,14 @@
#include <QStringList>
#include <qtextcodec.h>
#include <klocale.h>
+
#include "../core/robject.h"
#include "../debug.h"
#include "rklocalesupport.h"
#include "rkpthreadsupport.h"
#include "rksignalsupport.h"
+#include "../misc/rkcommonfunctions.h"
#include <stdlib.h>
#include <string.h>
@@ -233,6 +235,14 @@
Rf_error ("Backend dead"); // this jumps us out of the REPL.
}
+void REmbedInternal::tryToDoEmergencySave () {
+ RK_TRACE (RBACKEND);
+
+ // we're probably in a signal handler, and the stack base has changed.
+ R_CStackLimit = (uintptr_t)-1;
+ if (R_DirtyImage) R_SaveGlobalEnvToFile (RKCommonFunctions::getUseableRKWardSavefileName ("rkward_recover", ".RData").toLocal8Bit ());
+}
+
QStringList charPArrayToQStringList (const char** chars, int count) {
QStringList ret;
for (int i = 0; i < count; ++i) {
@@ -800,7 +810,7 @@
setupCallbacks ();
- RKSignalSupport::saveDefaultSigSegvHandler ();
+ RKSignalSupport::saveDefaultSignalHandlers ();
r_running = true;
Rf_initialize_R (argc, argv);
@@ -854,7 +864,7 @@
RKWard_RData_Tag = Rf_install ("RKWard_RData_Tag");
R_LastvalueSymbol = Rf_install (".Last.value");
- RKSignalSupport::installSigSegvProxy ();
+ RKSignalSupport::installSignalProxies ();
// register our functions
R_CallMethodDef callMethods [] = {
Modified: trunk/rkward/rkward/rbackend/rembedinternal.h
===================================================================
--- trunk/rkward/rkward/rbackend/rembedinternal.h 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rembedinternal.h 2010-10-07 14:55:19 UTC (rev 3112)
@@ -161,6 +161,7 @@
/** only one instance of this class may be around. This pointer keeps the reference to it, for interfacing to from C to C++ */
static REmbedInternal *this_pointer;
static char *na_char_internal;
+ static void tryToDoEmergencySave ();
bool r_running;
/** Check whether the runtime version of R is at least the given version. Valid only *after* startR() has been called! */
bool RRuntimeIsVersion (int major, int minor, int revision) {
Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp 2010-10-07 14:55:19 UTC (rev 3112)
@@ -137,6 +137,15 @@
return (QThread::currentThread () == RKGlobals::rInterface ()->r_thread);
}
+void RInterface::tryToDoEmergencySave () {
+ RK_TRACE (RBACKEND);
+ if (!inRThread ()) {
+ RKGlobals::rInterface ()->r_thread->terminate ();
+ RKGlobals::rInterface ()->r_thread->wait (1000);
+ }
+ RKGlobals::rInterface ()->r_thread->tryToDoEmergencySave ();
+}
+
void RInterface::startThread () {
RK_TRACE (RBACKEND);
@@ -317,13 +326,8 @@
if (request->call.count () >= 3) {
QString file_prefix = request->call[1];
QString file_extension = request->call[2];
- QDir dir (RKSettingsModuleGeneral::filesPath ());
-
- int i=0;
- while (dir.exists (file_prefix + QString::number (i) + file_extension)) {
- i++;
- }
- issueCommand (".rk.set.reply (\"" + dir.filePath (file_prefix + QString::number (i) + file_extension) + "\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
+
+ issueCommand (".rk.set.reply (\"" + RKCommonFunctions::getUseableRKWardSavefileName (file_prefix, file_extension) + "\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
} else {
issueCommand (".rk.set.reply (\"Too few arguments in call to get.tempfile.name.\")", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
}
Modified: trunk/rkward/rkward/rbackend/rinterface.h
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.h 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rinterface.h 2010-10-07 14:55:19 UTC (rev 3112)
@@ -92,6 +92,7 @@
bool backendIsIdle ();
static bool inRThread ();
+ static void tryToDoEmergencySave ();
public slots:
/** called periodically to flush output buffer in RThread */
void flushOutput ();
Modified: trunk/rkward/rkward/rbackend/rksignalsupport.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rksignalsupport.cpp 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rksignalsupport.cpp 2010-10-07 14:55:19 UTC (rev 3112)
@@ -2,7 +2,7 @@
rksignalsupport - description
-------------------
begin : Thu Nov 22 2007
- copyright : (C) 2007, 2009 by Thomas Friedrichsmeier
+ copyright : (C) 2007, 2009, 2010 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -33,84 +33,118 @@
#ifdef Q_WS_WIN
__sighandler_t r_sigsegv_handler = 0;
__sighandler_t default_sigsegv_handler = 0;
+ __sighandler_t r_sigill_handler = 0;
+ __sighandler_t default_sigill_handler = 0;
+ __sighandler_t r_sigabrt_handler = 0;
+ __sighandler_t default_sigabrt_handler = 0;
+#else
+ struct sigaction r_sigsegv_handler;
+ struct sigaction default_sigsegv_handler;
+ struct sigaction r_sigill_handler;
+ struct sigaction default_sigill_handler;
+ struct sigaction r_sigabrt_handler;
+ struct sigaction default_sigabrt_handler;
+#endif
- void sigsegv_proxy (int signum) {
+#ifdef Q_WS_WIN
+ void signal_proxy (int signum) {
+ __sighandler_t r_handler = r_sigsegv_handler;
+ __sighandler_t default_handler = default_sigsegv_handler;
#else
- struct sigaction r_sigsegv_action;
- struct sigaction default_sigsegv_action;
+ void signal_proxy (int signum, siginfo_t *info, void *context) {
+ struct sigaction r_handler = r_sigsegv_handler;
+ struct sigaction default_handler = default_sigsegv_handler;
+#endif
+ if (signum == SIGILL) {
+ r_handler = r_sigill_handler;
+ default_handler = default_sigill_handler;
+ } else if (signum == SIGABRT) {
+ r_handler = r_sigabrt_handler;
+ default_handler = default_sigabrt_handler;
+ } else {
+ RK_ASSERT (signum == SIGSEGV);
+ }
- void sigsegv_proxy (int signum, siginfo_t *info, void *context) {
-#endif
- RK_ASSERT (signum == SIGSEGV);
-
+ RInterface::tryToDoEmergencySave ();
+
// if we are not in the R thread, handling the signal in R does more harm than good.
if (RInterface::inRThread ()) {
#ifdef Q_WS_WIN
- if (r_sigsegv_handler) {
- r_sigsegv_handler (signum);
+ if (r_handler) {
+ r_handler (signum);
return;
}
#else
- if (r_sigsegv_action.sa_sigaction) {
- r_sigsegv_action.sa_sigaction (signum, info, context);
+ if (r_handler.sa_sigaction) {
+ r_handler.sa_sigaction (signum, info, context);
return;
- } else if (r_sigsegv_action.sa_handler) {
- r_sigsegv_action.sa_handler (signum);
+ } else if (r_handler.sa_handler) {
+ r_handler.sa_handler (signum);
return;
}
#endif
}
#ifdef Q_WS_WIN
- if (default_sigsegv_handler) {
- default_sigsegv_handler (signum);
+ if (default_handler) {
+ default_handler (signum);
return;
}
#else
// this might be a Qt/KDE override or default handling
- if (default_sigsegv_action.sa_sigaction) {
- default_sigsegv_action.sa_sigaction (signum, info, context);
+ if (default_handler.sa_sigaction) {
+ default_handler.sa_sigaction (signum, info, context);
return;
- } else if (default_sigsegv_action.sa_handler) {
- default_sigsegv_action.sa_handler (signum);
+ } else if (default_handler.sa_handler) {
+ default_handler.sa_handler (signum);
return;
}
#endif
-
- // not handled? should not happen
- RK_ASSERT (false);
-
- // do the default fallback handling
- signal (SIGSEGV, SIG_DFL);
- raise (SIGSEGV);
}
}
-void RKSignalSupport::saveDefaultSigSegvHandler () {
+void RKSignalSupport::saveDefaultSignalHandlers () {
RK_TRACE (RBACKEND);
#ifdef Q_WS_WIN
RKSignalSupportPrivate::default_sigsegv_handler = signal (SIGSEGV, SIG_DFL);
+ RKSignalSupportPrivate::default_sigill_handler = signal (SIGILL, SIG_DFL);
+ RKSignalSupportPrivate::default_sigabrt_handler = signal (SIGABRT, SIG_DFL);
#else
- sigaction (SIGSEGV, 0, &RKSignalSupportPrivate::default_sigsegv_action);
+ sigaction (SIGSEGV, 0, &RKSignalSupportPrivate::default_sigsegv_handler);
+ sigaction (SIGILL, 0, &RKSignalSupportPrivate::default_sigill_handler);
+ sigaction (SIGABRT, 0, &RKSignalSupportPrivate::default_sigabrt_handler);
#endif
}
-void RKSignalSupport::installSigSegvProxy () {
+void RKSignalSupport::installSignalProxies () {
RK_TRACE (RBACKEND);
#ifdef Q_WS_WIN
- RKSignalSupportPrivate::r_sigsegv_handler = signal (SIGSEGV, &RKSignalSupportPrivate::sigsegv_proxy);
+ RKSignalSupportPrivate::r_sigsegv_handler = signal (SIGSEGV, &RKSignalSupportPrivate::signal_proxy);
+ RKSignalSupportPrivate::r_sigill_handler = signal (SIGILL, &RKSignalSupportPrivate::signal_proxy);
+ RKSignalSupportPrivate::r_sigabrt_handler = signal (SIGABRT, &RKSignalSupportPrivate::signal_proxy);
#else
// retrieve R signal handler
- sigaction (SIGSEGV, 0, &RKSignalSupportPrivate::r_sigsegv_action);
+ sigaction (SIGSEGV, 0, &RKSignalSupportPrivate::r_sigsegv_handler);
+ sigaction (SIGILL, 0, &RKSignalSupportPrivate::r_sigill_handler);
+ sigaction (SIGABRT, 0, &RKSignalSupportPrivate::r_sigabrt_handler);
+ // set new proxy handlers
struct sigaction proxy_action;
- proxy_action = RKSignalSupportPrivate::r_sigsegv_action;
+ proxy_action = RKSignalSupportPrivate::r_sigsegv_handler;
proxy_action.sa_flags |= SA_SIGINFO;
- proxy_action.sa_sigaction = &RKSignalSupportPrivate::sigsegv_proxy;
+ proxy_action.sa_sigaction = &RKSignalSupportPrivate::signal_proxy;
+ sigaction (SIGSEGV, &proxy_action, 0);
- // set new proxy handler
- sigaction (SIGSEGV, &proxy_action, 0);
+ proxy_action = RKSignalSupportPrivate::r_sigill_handler;
+ proxy_action.sa_flags |= SA_SIGINFO;
+ proxy_action.sa_sigaction = &RKSignalSupportPrivate::signal_proxy;
+ sigaction (SIGILL, &proxy_action, 0);
+
+ proxy_action = RKSignalSupportPrivate::default_sigabrt_handler;
+ proxy_action.sa_flags |= SA_SIGINFO;
+ proxy_action.sa_sigaction = &RKSignalSupportPrivate::signal_proxy;
+ sigaction (SIGABRT, &proxy_action, 0);
#endif
}
Modified: trunk/rkward/rkward/rbackend/rksignalsupport.h
===================================================================
--- trunk/rkward/rkward/rbackend/rksignalsupport.h 2010-10-07 10:31:16 UTC (rev 3111)
+++ trunk/rkward/rkward/rbackend/rksignalsupport.h 2010-10-07 14:55:19 UTC (rev 3112)
@@ -2,7 +2,7 @@
rksignalsupport - description
-------------------
begin : Thu Nov 22 2007
- copyright : (C) 2007 by Thomas Friedrichsmeier
+ copyright : (C) 2007, 2010 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -19,8 +19,8 @@
#define RKSIGNALSUPPORT_H
namespace RKSignalSupport {
- void saveDefaultSigSegvHandler ();
- void installSigSegvProxy ();
+ void saveDefaultSignalHandlers ();
+ void installSignalProxies ();
};
#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