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 6116136afe
commit 86483b4d4b
9 changed files with 39 additions and 7 deletions

View File

@ -248,6 +248,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

@ -171,6 +171,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

@ -434,7 +434,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

@ -375,7 +375,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

@ -353,7 +353,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

@ -376,7 +376,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

@ -384,7 +384,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

@ -374,7 +374,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: