[education/rkward] rkward: Fix failure to restart backend, while inside R tempdir()

Thomas Friedrichsmeier null at kde.org
Fri Jul 5 16:33:16 BST 2024


Git commit 3a7924b9ff6b61a7f46023c651afd9ea46c19ed5 by Thomas Friedrichsmeier.
Committed on 05/07/2024 at 15:32.
Pushed by tfry into branch 'master'.

Fix failure to restart backend, while inside R tempdir()

M  +1    -0    rkward/autotests/core_test.cpp
M  +7    -4    rkward/rbackend/rkfrontendtransmitter.cpp
M  +9    -5    rkward/rbackend/rkrinterface.cpp
M  +1    -7    rkward/rkward.cpp

https://invent.kde.org/education/rkward/-/commit/3a7924b9ff6b61a7f46023c651afd9ea46c19ed5

diff --git a/rkward/autotests/core_test.cpp b/rkward/autotests/core_test.cpp
index 664a9bfc4..5a22b6f28 100644
--- a/rkward/autotests/core_test.cpp
+++ b/rkward/autotests/core_test.cpp
@@ -464,6 +464,7 @@ private Q_SLOTS:
 	}
 
 	void restartRBackend() {
+		RInterface::issueCommand(new RCommand("setwd(tempdir())", RCommand::User)); // retart used to fail, if in non-existant directory
 		RInterface::issueCommand(new RCommand("x <- 1", RCommand::User));
 		waitForAllFinished();
 		QVERIFY(RObjectList::getGlobalEnv()->findObject("x"));
diff --git a/rkward/rbackend/rkfrontendtransmitter.cpp b/rkward/rbackend/rkfrontendtransmitter.cpp
index 13cb721fd..019386352 100644
--- a/rkward/rbackend/rkfrontendtransmitter.cpp
+++ b/rkward/rbackend/rkfrontendtransmitter.cpp
@@ -234,7 +234,7 @@ void RKFrontendTransmitter::run () {
 	env.append(QStringLiteral("RK_BACKEND_LIB=") + backend_lib);
 #	else
 	env.append(QStringLiteral("RK_BACKEND_LIB=") + QFileInfo(backend_lib).fileName());
-	QTemporaryDir rkward_only_dir("rkward_only");
+	QTemporaryDir rkward_only_dir(QDir::tempPath() + "/rkward_only");
 	QFile(QFileInfo(backend_lib).absolutePath()).link(rkward_only_dir.filePath("_rkward_only_dlpath"));
 	env.append(QStringLiteral("RK_ADD_LDPATH=./_rkward_only_dlpath"));
 	env.append(QStringLiteral("RK_LD_CWD=") + rkward_only_dir.path());
@@ -242,9 +242,12 @@ void RKFrontendTransmitter::run () {
 #endif
 	backend->setEnvironment(env);
 
-#ifdef Q_OS_WIN
-	// Needed for paths with spaces. R CMD is too simple to deal with those, even if we provide proper quoting.
-	// So rather we need to work from a relative path with all spaces eliminated
+#ifndef Q_OS_MACOS
+	// Needed on for paths with spaces. R CMD is too simple to deal with those, even if we provide proper quoting.
+	// So rather we need to work from a relative path with all spaces eliminated.
+	// However, also, we might start in directory that no longer exists, or will cease to exist, in a second
+	// (e.g. the tempdir() of the previous R session). So we set something known to exist, here.
+	// On MacOS, we cd to R_HOME, instead, below
 	QFileInfo bfi(backend_executable);
 	backend->setWorkingDirectory(bfi.absolutePath());
 	args.append(bfi.fileName());
diff --git a/rkward/rbackend/rkrinterface.cpp b/rkward/rbackend/rkrinterface.cpp
index c20b91f1c..0503ba8c5 100644
--- a/rkward/rbackend/rkrinterface.cpp
+++ b/rkward/rbackend/rkrinterface.cpp
@@ -437,10 +437,6 @@ void RInterface::handleRequest (RBackendRequest* request) {
 			// initialize output file
 			RKOutputDirectory::getCurrentOutput(chain);
 
-#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
-			// On MacOS and Windows, the backend is started with different working directories set, for hackish reasons (see rkfrontendtransmitter.cpp). Fix that, here.
-			runStartupCommand(new RCommand("setwd (" + RKRSharedFunctionality::quote(QDir::currentPath()) + ")\n", RCommand::App | RCommand::Sync), chain, runtimeopt_callback);
-#endif
 			// Workaround for https://bugs.kde.org/show_bug.cgi?id=421958
 			if (RKSessionVars::compareRVersion("4.0.0") < 1 && RKSessionVars::compareRVersion("4.0.1") > 0) {
 				runStartupCommand(new RCommand("if(compiler::enableJIT(-1) > 2) compiler::enableJIT(2)\n", RCommand::App | RCommand::Sync), chain, runtimeopt_callback);
@@ -456,6 +452,14 @@ void RInterface::handleRequest (RBackendRequest* request) {
 			RK_ASSERT (command->getDataLength () == 1);
 			RKSettingsModuleR::help_base_url = command->stringVector ().value (0);
 		});
+
+		QString cd_to = RKSettingsModuleGeneral::initialWorkingDirectory();
+		cd_to = QDir::currentPath();
+		if (cd_to.isEmpty()) { // we must be in a non-existent dir. The backend will know better...
+			RInterface::issueCommand(new RCommand("setwd(\".\")\n", RCommand::App | RCommand::Sync), chain);
+		} else {
+			RInterface::issueCommand(new RCommand("setwd(" + RObject::rQuote(cd_to) + ")\n", RCommand::App | RCommand::Sync), chain);
+		}
 	} else {
 		processRBackendRequest (request);
 	}
@@ -666,7 +670,7 @@ GenericRRequestResult RInterface::processRCallRequest (const QString &call, cons
 		RK_ASSERT(arglist.count () == 1);
 		RKOutputWindowManager::self()->setCurrentOutputPath(arglist.value(0));
 	} else if (call == "wdChange") {
-		// in case of separate processes, apply new working directory in frontend, too.
+		// apply new working directory in frontend, too.
 		QDir::setCurrent(arglist.value(0));
 		Q_EMIT backendWorkdirChanged();
 	} else if (call == "highlightRCode") {
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index d6f911a20..77efc710a 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -255,12 +255,6 @@ void RKWardMainWindow::doPostInit () {
 		open_urls[i] = url.url ();
 	}
 
-	QString cd_to = RKSettingsModuleGeneral::initialWorkingDirectory ();
-	if (!cd_to.isEmpty ()) {
-		RInterface::issueCommand ("setwd (" + RObject::rQuote (cd_to) + ")\n", RCommand::App);
-		QDir::setCurrent (cd_to);
-	}
-
 	if (!open_urls.isEmpty()) {
 		// this is also done when there are no urls specified on the command line. But in that case _after_ loading any workspace, so
 		// the help window will be on top
@@ -288,7 +282,6 @@ void RKWardMainWindow::doPostInit () {
 	if (!evaluate_code.isEmpty ()) RKConsole::pipeUserCommand (evaluate_code);
 
 	updateCWD ();
-	connect (RInterface::instance(), &RInterface::backendWorkdirChanged, this, &RKWardMainWindow::updateCWD);
 	setCaption (QString ());	// our version of setCaption takes care of creating a correct caption, so we do not need to provide it here
 }
 
@@ -400,6 +393,7 @@ void RKWardMainWindow::startR () {
 	RInterface::create();
 	Q_EMIT backendCreated();
 	connect(RInterface::instance(), &RInterface::backendStatusChanged, this, &RKWardMainWindow::setRStatus);
+	connect(RInterface::instance(), &RInterface::backendWorkdirChanged, this, &RKWardMainWindow::updateCWD);
 	RObjectList::init();
 
 	RObjectBrowser::mainBrowser ()->unlock ();


More information about the rkward-tracker mailing list