aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-02-21 11:43:51 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-02-21 11:43:51 +0000
commit742feb0c89cb6d0cb0d61612ade2cca00c3dc362 (patch)
tree95f6c1156e33a7728c942ff85317a00ef6939e93
parent8ab5dd791fd53b7d88182cf264bc68221f814e89 (diff)
downloadrspamd-742feb0c89cb6d0cb0d61612ade2cca00c3dc362.tar.gz
rspamd-742feb0c89cb6d0cb0d61612ade2cca00c3dc362.zip
[Minor] Do a more clever sqlite locking
-rw-r--r--src/libutil/sqlite_utils.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/libutil/sqlite_utils.c b/src/libutil/sqlite_utils.c
index 7da003fa5..d4c5e9e20 100644
--- a/src/libutil/sqlite_utils.c
+++ b/src/libutil/sqlite_utils.c
@@ -207,6 +207,8 @@ static gboolean
rspamd_sqlite3_wait (rspamd_mempool_t *pool, const gchar *lock)
{
gint fd;
+ pid_t pid;
+ gssize r;
struct timespec sleep_ts = {
.tv_sec = 0,
.tv_nsec = 1000000
@@ -219,6 +221,46 @@ rspamd_sqlite3_wait (rspamd_mempool_t *pool, const gchar *lock)
return FALSE;
}
+
+ fd = open (lock, O_RDONLY);
+
+ if (fd == -1) {
+ msg_err_pool_check ("cannot open lock file %s: %s", lock,
+ strerror (errno));
+
+ return FALSE;
+ }
+
+ r = read (fd, &pid, sizeof (pid));
+
+ if (r != sizeof (pid)) {
+ msg_warn_pool_check ("stale lock file %s, removing", lock);
+ unlink (lock);
+ close (fd);
+
+ return TRUE;
+ }
+
+ /* Now check for process existence */
+ if (pid == getpid ()) {
+ msg_warn_pool_check ("lock file %s, belongs to me, removing", lock);
+ unlink (lock);
+ close (fd);
+
+ return TRUE;
+ }
+ else if (kill (pid, 0) == -1) {
+ if (errno == ESRCH) {
+ /* Process is already dead */
+ msg_warn_pool_check ("stale lock file %s from pid: %P, removing",
+ lock, pid);
+ unlink (lock);
+ close (fd);
+
+ return TRUE;
+ }
+ }
+
if (nanosleep (&sleep_ts, NULL) == -1 && errno != EINTR) {
msg_err_pool_check ("cannot sleep open lock file %s: %s", lock,
strerror (errno));
@@ -308,7 +350,9 @@ rspamd_sqlite3_open_or_create (rspamd_mempool_t *pool, const gchar *path, const
has_lock = FALSE;
}
else {
+ pid_t myself = getpid ();
msg_debug_pool_check ("locking %s to block other processes", lock_path);
+ (void)write (lock_fd, &myself, sizeof (myself));
g_assert (rspamd_file_lock (lock_fd, FALSE));
has_lock = TRUE;