Skip to content

Commit 109deba

Browse files
committed
Prevent race condition with concurrent cleanup operation in RobustSharedLock
Signed-off-by: Matthias Schneider <[email protected]>
1 parent d4bbcdb commit 109deba

File tree

1 file changed

+40
-27
lines changed

1 file changed

+40
-27
lines changed

src/cpp/utils/shared_memory/RobustSharedLock.hpp

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -237,40 +237,53 @@ class RobustSharedLock
237237
bool* was_lock_created,
238238
bool* was_lock_released)
239239
{
240-
auto fd = open(file_path.c_str(), O_RDONLY, 0);
240+
int fd = -1;
241+
do {
242+
fd = open(file_path.c_str(), O_RDONLY, 0);
241243

242-
if (fd != -1)
243-
{
244-
*was_lock_created = false;
245-
}
246-
else
247-
{
248-
*was_lock_created = true;
249-
fd = open(file_path.c_str(), O_CREAT | O_RDONLY, 0666);
250-
}
251-
252-
if (was_lock_released != nullptr)
253-
{
254-
// Lock exclusive
255-
if (0 == flock(fd, LOCK_EX | LOCK_NB))
244+
if (fd != -1)
256245
{
257-
// Exclusive => shared
258-
flock(fd, LOCK_SH | LOCK_NB);
259-
*was_lock_released = true;
260-
return fd;
246+
*was_lock_created = false;
261247
}
262248
else
263249
{
264-
*was_lock_released = false;
250+
*was_lock_created = true;
251+
fd = open(file_path.c_str(), O_CREAT | O_RDONLY, 0666);
265252
}
266-
}
267253

268-
// Lock shared
269-
if (0 != flock(fd, LOCK_SH | LOCK_NB))
270-
{
271-
close(fd);
272-
throw std::runtime_error(("failed to lock " + file_path).c_str());
273-
}
254+
if (was_lock_released != nullptr)
255+
{
256+
// Lock exclusive
257+
if (0 == flock(fd, LOCK_EX | LOCK_NB))
258+
{
259+
// Check if file was deleted by clean up script between open and lock
260+
// if yes, repeat file creation
261+
struct stat buffer = {};
262+
if (stat(file_path.c_str(), &buffer) != 0 && errno == ENOENT)
263+
{
264+
close(fd);
265+
fd = -1;
266+
continue;
267+
}
268+
269+
// Exclusive => shared
270+
flock(fd, LOCK_SH | LOCK_NB);
271+
*was_lock_released = true;
272+
return fd;
273+
}
274+
else
275+
{
276+
*was_lock_released = false;
277+
}
278+
}
279+
280+
// Lock shared
281+
if (0 != flock(fd, LOCK_SH | LOCK_NB))
282+
{
283+
close(fd);
284+
throw std::runtime_error(("failed to lock " + file_path).c_str());
285+
}
286+
} while (fd == -1);
274287

275288
return fd;
276289
}

0 commit comments

Comments
 (0)