fixed GH #990: Potential race condition in on Windows

This commit is contained in:
Guenter Obiltschnig 2016-11-03 14:48:51 +01:00
parent c59ec564c2
commit efdeadef2a
9 changed files with 39 additions and 7 deletions

View File

@ -254,6 +254,7 @@ POCO_DECLARE_EXCEPTION(Foundation_API, CreateFileException, FileException)
POCO_DECLARE_EXCEPTION(Foundation_API, OpenFileException, FileException)
POCO_DECLARE_EXCEPTION(Foundation_API, WriteFileException, FileException)
POCO_DECLARE_EXCEPTION(Foundation_API, ReadFileException, FileException)
POCO_DECLARE_EXCEPTION(Foundation_API, DirectoryNotEmptyException, FileException)
POCO_DECLARE_EXCEPTION(Foundation_API, UnknownURISchemeException, RuntimeException)
POCO_DECLARE_EXCEPTION(Foundation_API, TooManyURIRedirectsException, RuntimeException)
POCO_DECLARE_EXCEPTION(Foundation_API, URISyntaxException, SyntaxException)

View File

@ -178,6 +178,7 @@ POCO_IMPLEMENT_EXCEPTION(CreateFileException, FileException, "Cannot create file
POCO_IMPLEMENT_EXCEPTION(OpenFileException, FileException, "Cannot open file")
POCO_IMPLEMENT_EXCEPTION(WriteFileException, FileException, "Cannot write file")
POCO_IMPLEMENT_EXCEPTION(ReadFileException, FileException, "Cannot read file")
POCO_IMPLEMENT_EXCEPTION(DirectoryNotEmptyException, FileException, "Directory not empty")
POCO_IMPLEMENT_EXCEPTION(UnknownURISchemeException, RuntimeException, "Unknown URI scheme")
POCO_IMPLEMENT_EXCEPTION(TooManyURIRedirectsException, RuntimeException, "Too many URI redirects")
POCO_IMPLEMENT_EXCEPTION(URISyntaxException, SyntaxException, "Bad URI syntax")

View File

@ -34,6 +34,7 @@
#else
#include "File_VMS.cpp"
#endif
#include "Poco/Thread.h"
namespace Poco {
@ -269,8 +270,37 @@ void File::remove(bool recursive)
{
it->remove(true);
}
// Note: On Windows, removing a directory may not succeed at first
// try because deleting files is not a synchronous operation. Files
// are merely marked as deleted, and actually removed at a later time.
//
// An alternate strategy would be moving files to a different directory
// first (on the same drive, but outside the deleted tree), and marking
// them as hidden, before deleting them, but this could lead to other issues.
// So we simply retry after some time until we succeed, or give up.
int retry = 8;
long sleep = 10;
while (retry > 0)
{
try
{
removeImpl();
retry = 0;
}
catch (DirectoryNotEmptyException&)
{
if (--retry == 0) throw;
Poco::Thread::sleep(sleep);
sleep *= 2;
}
}
}
else
{
removeImpl();
}
removeImpl();
}

View File

@ -507,7 +507,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
throw FileException("disk quota exceeded", path, errno);
#if !defined(_AIX)
case ENOTEMPTY:
throw FileException("directory not empty", path, errno);
throw DirectoryNotEmptyException(path, errno);
#endif
case ENAMETOOLONG:
throw PathSyntaxException(path, errno);

View File

@ -405,7 +405,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
case EDQUOT:
throw FileException("disk quota exceeded", path);
case ENOTEMPTY:
throw FileException("directory not empty", path);
throw DirectoryNotEmptyException(path, err);
case ENAMETOOLONG:
throw PathSyntaxException(path);
default:

View File

@ -389,7 +389,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
case ENOSPC:
throw FileException("no space left on device", path);
case ENOTEMPTY:
throw FileException("directory not empty", path);
throw DirectoryNotEmptyException(path);
case ENAMETOOLONG:
throw PathSyntaxException(path);
case ENFILE:

View File

@ -409,7 +409,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
case ERROR_CANNOT_MAKE:
throw CreateFileException(path, err);
case ERROR_DIR_NOT_EMPTY:
throw FileException("directory not empty", path, err);
throw DirectoryNotEmptyException(path, err);
case ERROR_WRITE_FAULT:
throw WriteFileException(path, err);
case ERROR_READ_FAULT:

View File

@ -417,7 +417,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
case ERROR_CANNOT_MAKE:
throw CreateFileException(path, err);
case ERROR_DIR_NOT_EMPTY:
throw FileException("directory not empty", path, err);
throw DirectoryNotEmptyException(path, err);
case ERROR_WRITE_FAULT:
throw WriteFileException(path, err);
case ERROR_READ_FAULT:

View File

@ -407,7 +407,7 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
case ERROR_CANNOT_MAKE:
throw CreateFileException(path);
case ERROR_DIR_NOT_EMPTY:
throw FileException("directory not empty", path);
throw DirectoryNotEmptyException(path);
case ERROR_WRITE_FAULT:
throw WriteFileException(path);
case ERROR_READ_FAULT: