Mask signals while updating database

In order to keep the database consistent, we really want all the
AtomicFiles to be finalized as a group. This will prevent an inopportune
signal from interrupting this process.

Signed-off-by: Shaun Ruffell <sruffell@sruffell.net>
This commit is contained in:
Shaun Ruffell 2020-05-09 14:42:18 -05:00 committed by lauft
parent 83ec55cdc6
commit 59d0f1263f

View file

@ -24,11 +24,13 @@
// //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <csignal>
#include <stdio.h> #include <stdio.h>
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <unistd.h> #include <unistd.h>
#include <timew.h>
#include <format.h> #include <format.h>
#include <AtomicFile.h> #include <AtomicFile.h>
@ -231,6 +233,7 @@ void AtomicFile::impl::finalize ()
{ {
if (is_temp_active && impl::allow_atomics) if (is_temp_active && impl::allow_atomics)
{ {
debug (format ("Moving '{1}' -> '{2}'", temp_file._data, real_file._data));
if (std::rename (temp_file._data.c_str (), real_file._data.c_str ())) if (std::rename (temp_file._data.c_str (), real_file._data.c_str ()))
{ {
throw format("Failed copying '{1}' to '{2}'. Database corruption possible.", throw format("Failed copying '{1}' to '{2}'. Database corruption possible.",
@ -415,13 +418,23 @@ void AtomicFile::finalize_all ()
file->close (); file->close ();
} }
atomic_files_t new_atomic_files;
// Step 2: Rename the temp files to the *real* files sigset_t new_mask;
sigset_t old_mask;
sigfillset (&new_mask);
// Step 2: Rename the temp files to the *real* file
sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
for (auto& file : impl::atomic_files) for (auto& file : impl::atomic_files)
{ {
file->finalize (); file->finalize ();
}
sigprocmask (SIG_SETMASK, &old_mask, nullptr);
// Step 3: Cleanup any references
atomic_files_t new_atomic_files;
for (auto& file : impl::atomic_files)
{
// Delete entry if we are holding the last reference // Delete entry if we are holding the last reference
if (file.use_count () > 1) if (file.use_count () > 1)
{ {