[education/rkward] rkward/rbackend: Fix backend exit routine

Thomas Friedrichsmeier null at kde.org
Sat Aug 6 12:53:09 BST 2022


Git commit 98bbe0b7470f6db346d356cbb08e3b55584fcf75 by Thomas Friedrichsmeier.
Committed on 06/08/2022 at 11:53.
Pushed by tfry into branch 'master'.

Fix backend exit routine

M  +8    -4    rkward/rbackend/rkrbackend.cpp
M  +12   -4    rkward/rbackend/rkrbackendprotocol_backend.cpp
M  +4    -0    rkward/rbackend/rkrbackendprotocol_backend.h

https://invent.kde.org/education/rkward/commit/98bbe0b7470f6db346d356cbb08e3b55584fcf75

diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index ebca3016..a481fb50 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -265,9 +265,10 @@ int RReadConsole (const char* prompt, unsigned char* buf, int buflen, int hist)
 	
 	if ((!RKRBackend::repl_status.browser_context) && (RKRBackend::repl_status.eval_depth == 0)) {
 		while (true) {
-			if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::NoUserCommand) {
+			if (RKRBackend::this_pointer->isKilled() || (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::NoUserCommand)) {
 				RCommandProxy *command = RKRBackend::this_pointer->fetchNextCommand ();
 				if (!command) {
+					RK_DEBUG(RBACKEND, DL_DEBUG, "returning from REPL");
 #ifdef Q_OS_WIN
 					// Can't easily override R_CleanUp on Windows, so we're calling it manually, here, then force exit
 					if (RKRBackend::this_pointer->killed == RKRBackend::ExitNow) RCleanUp (SA_NOSAVE, 0, 0);
@@ -559,9 +560,9 @@ void RCleanUp (SA_TYPE saveact, int status, int RunLast) {
 			filename = dir.absoluteFilePath (filename);
 
 			R_SaveGlobalEnvToFile (filename.toLocal8Bit ().data ());
-			qDebug ("Created emergency save file in %s", qPrintable (filename));
+			RK_DEBUG(RBACKEND, DL_WARNING, "Created emergency save file in %s", qPrintable(filename));
 		} else {
-			qDebug ("Image not dirty while crashing. No emergency save created.");
+			RK_DEBUG(RBACKEND, DL_WARNING, "Image not dirty while crashing. No emergency save created.");
 		}
 	}
 
@@ -571,7 +572,7 @@ void RCleanUp (SA_TYPE saveact, int status, int RunLast) {
 			request.params["message"] = QVariant (i18n ("The R engine has shut down with status: %1", status));
 			RKRBackend::this_pointer->handleRequest (&request);
 		}
-
+		RK_DEBUG(RBACKEND, DL_DEBUG, "Cleaning up");
 		R_RunExitFinalizers ();
 		Rf_KillAllDevices ();
 		R_CleanTempDir ();
@@ -580,6 +581,8 @@ void RCleanUp (SA_TYPE saveact, int status, int RunLast) {
 	RKRBackend::this_pointer->killed = RKRBackend::AlreadyDead;	// just in case
 
 	R_CStackLimit = old_lim;	// well, it should not matter any longer, but...
+	RK_DEBUG(RBACKEND, DL_DEBUG, "Cleanup finished");
+	RKRBackendProtocolBackend::doExit();
 }
 
 void RSuicide (const char* message) {
@@ -1238,6 +1241,7 @@ void RKRBackend::enterEventLoop () {
 
 	run_Rmainloop ();
 	// NOTE: Do NOT run Rf_endEmbeddedR(). It does more that we want. We rely on RCleanup, instead.
+	// NOTE: never reached with R since ?? at least 4.3: RCleanUp is expected to exit the process
 	RK_DEBUG(RBACKEND, DL_DEBUG, "R loop finished");
 }
 
diff --git a/rkward/rbackend/rkrbackendprotocol_backend.cpp b/rkward/rbackend/rkrbackendprotocol_backend.cpp
index b5b0696c..ee5abde4 100644
--- a/rkward/rbackend/rkrbackendprotocol_backend.cpp
+++ b/rkward/rbackend/rkrbackendprotocol_backend.cpp
@@ -110,20 +110,28 @@ SPDX-License-Identifier: GPL-2.0-or-later
 		QString token = QUuid::createUuid ().toString ();
 
 		RKRBackendTransmitter transmitter (servername, token);
+		RKRBackendProtocolBackend::p_transmitter = &transmitter;
 		RKRBackendProtocolBackend backend (data_dir, rkd_server_name);
 		transmitter.start ();
 		RKRBackend::this_pointer->run (locale_dir);
+		// NOTE:: Since some unknown version of R (4.3.0 at the latest, but probabably much earlier), run_Rmainloop() does not return, it will
+		//        eventually exit, instead.
+		RKRBackendProtocolBackend::doExit();
+	}
+
+	void RKRBackendProtocolBackend::doExit() {
 		RK_DEBUG(RBACKEND, DL_DEBUG, "Main loop finished");
 
-		QMetaObject::invokeMethod(&transmitter, "doExit", Qt::QueuedConnection);
-		transmitter.wait (5000);
+		QMetaObject::invokeMethod(p_transmitter, "doExit", Qt::QueuedConnection);
+		p_transmitter->wait (5000);
 
 		if (!RKRBackend::this_pointer->isKilled ()) RKRBackend::tryToDoEmergencySave ();
-		QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
+		QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
 		exit(0);
 	}
 
-RKRBackendProtocolBackend* RKRBackendProtocolBackend::_instance = 0;
+RKRBackendProtocolBackend* RKRBackendProtocolBackend::_instance = nullptr;
+RKRBackendTransmitter* RKRBackendProtocolBackend::p_transmitter = nullptr;
 RKRBackendProtocolBackend::RKRBackendProtocolBackend (const QString &storage_dir, const QString &_rkd_server_name) {
 	RK_TRACE (RBACKEND);
 
diff --git a/rkward/rbackend/rkrbackendprotocol_backend.h b/rkward/rbackend/rkrbackendprotocol_backend.h
index 90dbd5e9..8ff35473 100644
--- a/rkward/rbackend/rkrbackendprotocol_backend.h
+++ b/rkward/rbackend/rkrbackendprotocol_backend.h
@@ -11,6 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "rkrbackendprotocol_shared.h"
 
 class QThread;
+class RKRBackendTransmitter;
 
 class RKRBackendProtocolBackend {
 public:
@@ -18,6 +19,7 @@ public:
 	static QString dataDir () { return _instance->data_dir; };
 	static QString rkdServerName () { return _instance->rkd_server_name; };
 	static QString backendDebugFile ();
+	static void doExit();
 
 	RKRBackendProtocolBackend (const QString &data_dir, const QString &rkd_server_name);
 	~RKRBackendProtocolBackend ();
@@ -26,6 +28,7 @@ friend class RKRBackendProtocolFrontend;
 friend class RKRBackend;
 friend class RKRBackendThread;
 friend class RKRBackendTransmitter;
+friend int main(int, char**);
 	void sendRequest (RBackendRequest *request);
 	static void msleep (int delay);
 	static RKRBackendProtocolBackend* instance () { return _instance; };
@@ -33,6 +36,7 @@ friend class RKRBackendTransmitter;
 private:
 	QString rkd_server_name;
 	static RKRBackendProtocolBackend* _instance;
+	static RKRBackendTransmitter* p_transmitter;
 	QThread *r_thread;
 #ifndef Q_OS_WIN
 	friend void completeForkChild ();


More information about the rkward-tracker mailing list