www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Call of rmdir in destructor causes InvalidMemoryOperationError

reply Timo Gransch <timo.gransch web.de> writes:
Hi,

I have a class which unzips an archive into a temporary directory below the
system temp folder. I want to delete this temporary directory in the class's
destructor, but when I call rmdir there, I get an

core.exception.InvalidMemoryOperationError (0)

The effect is not limited to this special case. Whenever I call rmdir in the
destructor, no matter for which directory, I get the same error.

Environment: DMD v2.066.1 (from D-Apt) on Ubuntu 14.10 (32 and 64 bit).

Sample code:

// -------------------------------------------
module main;

import std.stdio;
import std.file;
import std.path;

class RmdirTest
{
	private string sTempDir;

	this(string sInstanceName)
	{
		writeln("Constructor called");
		sTempDir=tempDir() ~ dirSeparator ~ sInstanceName;
		mkdir (sTempDir);
	}

	~this()
	{
		writeln("Destructor called");

		if (sTempDir !is null)
		{
			rmdir(sTempDir);
		}
	}
}

void main(string[] args)
{
	RmdirTest rmDirTest=new RmdirTest("123");
}
// -------------------------------------------

Console output is:

Constructor called
Destructor called
core.exception.InvalidMemoryOperationError (0)

The directory "/tmp/123" is created, but not deleted.

When I change the line "(sTempDir !is null)" to "((sTempDir !is null) &&
(exists(sTempDir)) && (isDir(sTempDir)))", the exception is thrown already on
this line, so obviously  the problem also applies to other file functions like
exists and isDir.

Is there any solution for this?

Thanks and best regards,
Timo
Jan 01 2015
next sibling parent Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
Timo Gransch via Digitalmars-d-learn píše v Čt 01. 01. 2015 v 16:14
+0100:
 Hi,
 
 I have a class which unzips an archive into a temporary directory below the
system temp folder. I want to delete this temporary directory in the class's
destructor, but when I call rmdir there, I get an
 
 core.exception.InvalidMemoryOperationError (0)
 
 The effect is not limited to this special case. Whenever I call rmdir in the
destructor, no matter for which directory, I get the same error.
 
 Environment: DMD v2.066.1 (from D-Apt) on Ubuntu 14.10 (32 and 64 bit).
 
 Sample code:
 
 // -------------------------------------------
 module main;
 
 import std.stdio;
 import std.file;
 import std.path;
 
 class RmdirTest
 {
 	private string sTempDir;
 
 	this(string sInstanceName)
 	{
 		writeln("Constructor called");
 		sTempDir=tempDir() ~ dirSeparator ~ sInstanceName;
 		mkdir (sTempDir);
 	}
 
 	~this()
 	{
 		writeln("Destructor called");
 
 		if (sTempDir !is null)
 		{
 			rmdir(sTempDir);
 		}
 	}
 }
 
 void main(string[] args)
 {
 	RmdirTest rmDirTest=new RmdirTest("123");
 }
 // -------------------------------------------
 
 Console output is:
 
 Constructor called
 Destructor called
 core.exception.InvalidMemoryOperationError (0)
 
 The directory "/tmp/123" is created, but not deleted.
 
 When I change the line "(sTempDir !is null)" to "((sTempDir !is null) &&
(exists(sTempDir)) && (isDir(sTempDir)))", the exception is thrown already on
this line, so obviously  the problem also applies to other file functions like
exists and isDir.
 
 Is there any solution for this?
 
 Thanks and best regards,
 Timo
You shoud not use destructor for this operation. In D there is no guarantee that class destructor will be called. So you can probablly use struct instead of class or add some method and called it explicitly when needed
Jan 01 2015
prev sibling parent reply "thedeemon" <dlang thedeemon.com> writes:
On Thursday, 1 January 2015 at 15:14:41 UTC, Timo Gransch wrote:
 Hi,

 I have a class which unzips an archive into a temporary 
 directory below the system temp folder. I want to delete this 
 temporary directory in the class's destructor, but when I call 
 rmdir there, I get an

 core.exception.InvalidMemoryOperationError (0)
Destructors are usually called by GC, during a GC cycle, so allocating and deallocating memory is not allowed there. If some function allocates, reallocates or deallocates, it will cause this very error. This means you shouldn't use any functions in a destructor that are not nogc. Solution in this case: call rmdir not from destructor.
Jan 01 2015
parent Timo Gransch <timo.gransch web.de> writes:
Am Thu, 01 Jan 2015 16:07:06 +0000
schrieb "thedeemon" <dlang thedeemon.com>:

 Solution in this case: call rmdir not from destructor.
Thanks (also to Daniel Kozak) for the information. I moved the functionality to an explicitly called method. Best regards, Timo
Jan 01 2015