mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-16 03:42:53 +01:00
fixed GH #990: Potential race condition in on Windows
This commit is contained in:
parent
c59ec564c2
commit
efdeadef2a
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user