[rkward/frameworks] rkward/rbackend/rkwarddevice: Fix MSVC-compiled backend crash on RK()-device close.

Thomas Friedrichsmeier thomas.friedrichsmeier at ruhr-uni-bochum.de
Sun Feb 28 17:15:38 UTC 2016

Git commit 8fcbd52dfca73b9ee6e8f3266c7b2eb94336825b by Thomas Friedrichsmeier.
Committed on 28/02/2016 at 17:15.
Pushed by tfry into branch 'frameworks'.

Fix MSVC-compiled backend crash on RK()-device close.

M  +13   -1    rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
M  +11   -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp


diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
index 90a3a40..5afd04d 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
@@ -55,6 +55,10 @@ struct RKGraphicsDeviceDesc {
 	QString default_family;
 	QString default_symbol_family;
 	pDevDesc rdevdesc;
+#ifdef _MSC_VER
+	// See RKD_Close()
+	pGEDevDesc rgdevdesc;
 #include "rkgraphicsdevice_stubs.cpp"
@@ -76,7 +80,11 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
 	pDevDesc dev;
 		/* Allocate and initialize the device driver data */
-		dev = (pDevDesc) calloc (1, sizeof(DevDesc));
+#ifdef _MSC_VER
+		dev = (pDevDesc) malloc (sizeof (DevDesc));
+		dev = (pDevDesc) calloc (1, sizeof (DevDesc)); // don't really understand this, but R needs it this way (while MSVC hates it)
 		// NOTE: The call to RKGraphicsDeviceBackendTransmitter::instance(), here is important beyond error checking. It might *create* the instance and connection, if this is the first use.
 		if (!(dev && RKGraphicsDeviceBackendTransmitter::instance () && desc->init (dev, pointsize, family, bg))) {
 			free (dev);
@@ -89,6 +97,10 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
 			pGEDevDesc gdd = GEcreateDevDesc (dev);
 			gdd->displayList = R_NilValue;
 			GEaddDevice2 (gdd, "RKGraphicsDevice");
+#ifdef _MSC_VER
+			// See RKD_Close()
+			desc->rgdevdesc = gdd;
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index c6c619a..217fbcd 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -360,6 +360,17 @@ static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* de
 static void RKD_Close (pDevDesc dev) {
 	RKGraphicsDataStreamWriteGuard guard;
 	WRITE_HEADER (RKDClose, dev);
+#ifdef _MSC_VER
+	// Ok, this is a terribly crude HACK, obivously, and it's just waiting to come back to bite us. However:
+	// We had to allocate the DevDesc in our own (MSVC-compiled) code (that's the way it is done), but if we allow R to delete
+	// it (also, as usual; in its MinGW-compiled code), we get a crash. Whatever the _exact_ reason. So what we do here is
+	// reset R's pointer, and do the free, ourselves. Fortunately, we can do this, and fortunately, the pointer is no longer
+	// needed at this point. At least not in R 3.2.3...
+        // If (or when) this breaks, we could try to just call some other device's init-routine, then hijack that device. Or out-source
+        // the RKGraphicsDevice backend init code into an R package...
+	static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->rgdevdesc->dev = NULL;
+	free (dev);
 	delete static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific);

More information about the rkward-tracker mailing list