summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2021-04-29 19:03:26 +0300
committerSergey Poznyakoff <gray@gnu.org>2021-04-29 19:11:20 +0300
commit9eca2fa180cb562128a9db1bad8c77d0b3bdc6a4 (patch)
tree76e402ef9ed270619d6618a060de75237f10bda1 /libmailutils
parent6a1152b883407a5cc7d77faa023d2948ac70e8de (diff)
downloadmailutils-9eca2fa180cb562128a9db1bad8c77d0b3bdc6a4.tar.gz
mailutils-9eca2fa180cb562128a9db1bad8c77d0b3bdc6a4.tar.bz2
Further improvements of the locker interface.
This fixes a bug that prevented previous versions of mailutils to retry aquiring the lock. Locking configuration (the "locking" section) is improved. * dotlock/dotlock.c: New options: --retry (-r), --delay (-t), --pid-check (-p). Use the "locking" capability. * libmailutils/base/locker.c: Remove the uses of assert(). (mu_locker_lock_mode): Fix the retry loop. (lock_dotlock): Use mu_asprintf to create temporary lock name. Return EAGAIN on temporary error conditions. (lock_kernel): Fix typo (EACCES). * libmailutils/cli/stdcapa.c (cb_locker_flags): Locker flags are deprecated. (cb_locker_retry_timeout,cb_locker_retry_count): Clear the MU_LOCKER_RETRY flag, if supplied a zero value. (cb_locker_external): Clear the MU_LOCKER_EXTERNAL flag (revert to the dotlock locker type) if the value is a false boolean value. * libmailutils/tests/Makefile.am: Add new test. * libmailutils/tests/testsuite.at: Include new test, * libmailutils/tests/lck.c: New test program. * libmailutils/tests/lock.at: New test.
Diffstat (limited to 'libmailutils')
-rw-r--r--libmailutils/base/locker.c81
-rw-r--r--libmailutils/cli/stdcapa.c89
-rw-r--r--libmailutils/tests/.gitignore1
-rw-r--r--libmailutils/tests/Makefile.am2
-rw-r--r--libmailutils/tests/lck.c335
-rw-r--r--libmailutils/tests/lock.at59
-rw-r--r--libmailutils/tests/testsuite.at2
7 files changed, 496 insertions, 73 deletions
diff --git a/libmailutils/base/locker.c b/libmailutils/base/locker.c
index 72634b0c9..ef26fc52b 100644
--- a/libmailutils/base/locker.c
+++ b/libmailutils/base/locker.c
@@ -19,7 +19,6 @@
# include <config.h>
#endif
-#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -40,6 +39,7 @@
#include <mailutils/errno.h>
#include <mailutils/locker.h>
#include <mailutils/util.h>
+#include <mailutils/io.h>
#define LOCKFILE_ATTR 0644
@@ -57,17 +57,21 @@ struct _mu_locker
int retries;
int retry_sleep;
- union lock_data {
- struct {
+ union lock_data
+ {
+ struct
+ {
char *dotlock;
char *nfslock;
} dot;
- struct {
+ struct
+ {
char *name;
} external;
- struct {
+ struct
+ {
int fd;
} kernel;
} data;
@@ -581,19 +585,19 @@ mu_locker_lock_mode (mu_locker_t lock, enum mu_locker_mode mode)
{
rc = locker_tab[type].lock (lock, mode);
if (rc == EAGAIN && retries)
- {
- sleep (lock->retry_sleep);
- continue;
- }
-
- if (rc == 0)
- lock->refcnt++;
-
- break;
+ sleep (lock->retry_sleep);
+ else
+ break;
}
+
+ if (rc == EAGAIN)
+ rc = MU_ERR_LOCK_CONFLICT;
}
else
rc = 0;
+
+ if (rc == 0)
+ lock->refcnt++;
return rc;
}
@@ -746,9 +750,7 @@ lock_dotlock (mu_locker_t locker, enum mu_locker_mode mode)
{
int rc;
char *host = NULL;
- char pid[11]; /* 10 is strlen(2^32 = 4294967296) */
- char now[11];
- size_t sz = 0;
+ time_t now;
int err = 0;
int fd;
@@ -766,29 +768,15 @@ lock_dotlock (mu_locker_t locker, enum mu_locker_mode mode)
rc = mu_get_host_name (&host);
if (rc)
return rc;
-
- snprintf (now, sizeof (now), "%lu", (unsigned long) time (0));
- now[sizeof (now) - 1] = 0;
-
- snprintf (pid, sizeof (pid), "%lu", (unsigned long) getpid ());
- pid[sizeof (pid) - 1] = 0;
-
- sz = strlen (locker->file) + 1 /* "." */
- + strlen (pid) + 1 /* "." */
- + strlen (now) + 1 /* "." */
- + strlen (host) + 1;
-
- locker->data.dot.nfslock = malloc (sz);
-
- if (!locker->data.dot.nfslock)
- {
- free (host);
- return ENOMEM;
- }
-
- snprintf (locker->data.dot.nfslock, sz, "%s.%s.%s.%s",
- locker->file, pid, now, host);
+ time (&now);
+ rc = mu_asprintf (&locker->data.dot.nfslock,
+ "%s.%lu.%lu.%s",
+ locker->file,
+ (unsigned long) getpid (),
+ (unsigned long) now, host);
free (host);
+ if (rc)
+ return rc;
fd = open (locker->data.dot.nfslock,
O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_ATTR);
@@ -806,7 +794,7 @@ lock_dotlock (mu_locker_t locker, enum mu_locker_mode mode)
{
unlink (locker->data.dot.nfslock);
if (errno == EEXIST)
- return MU_ERR_LOCK_CONFLICT;
+ return EAGAIN;
return errno;
}
@@ -827,9 +815,6 @@ lock_dotlock (mu_locker_t locker, enum mu_locker_mode mode)
unlink (locker->data.dot.nfslock);
- /* FIXME: If no errors, we have the lock. */
- assert (locker->refcnt == 0);
-
if (locker->flags & MU_LOCKER_PID)
{
char buf[16];
@@ -913,8 +898,8 @@ lock_kernel (mu_locker_t locker, enum mu_locker_mode mode)
fl.l_len = 0; /* Lock entire file */
if (fcntl (fd, F_SETLK, &fl))
{
-#ifdef EACCESS
- if (errno == EACCESS)
+#ifdef EACCES
+ if (errno == EACCES)
return EAGAIN;
#endif
if (errno == EAGAIN)
@@ -978,12 +963,6 @@ external_locker (mu_locker_t l, int lock)
char aretry[3 + DEC_DIGS_PER_INT + 1];
int status = 0;
- assert (l);
- assert (l->flags & MU_LOCKER_EXTERNAL);
- /* FIXME */
- assert (lock == !l->refcnt);
- /* lock is true, refcnt is 0 or lock is false and refcnt is 1 */
-
av[ac++] = l->data.external.name ?
l->data.external.name : MU_LOCKER_EXTERNAL_PROGRAM;
diff --git a/libmailutils/cli/stdcapa.c b/libmailutils/cli/stdcapa.c
index afa5443e1..b72f024cb 100644
--- a/libmailutils/cli/stdcapa.c
+++ b/libmailutils/cli/stdcapa.c
@@ -30,6 +30,7 @@
#include <mailutils/locker.h>
#include <mailutils/mu_auth.h>
#include <mailutils/url.h>
+#include <mailutils/kwd.h>
/* *************************************************************************
* Logging section
@@ -308,35 +309,44 @@ cb_locker_flags (void *data, mu_config_value_t *val)
{
int flags = 0;
char const *s;
-
+ static struct mu_kwd flag_tab[] = {
+ { "external-locker", 'E' },
+ { "retry-count", 'R' },
+ { "expire-timeout", 'T' },
+ { "pid-check", 'P' },
+ { NULL }
+ };
+
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
for (s = val->v.string; *s; s++)
{
- switch (*s)
+ char const *kw;
+ if (mu_kwd_xlat_tok (flag_tab, *s, &kw))
{
- case 'E':
- flags |= MU_LOCKER_EXTERNAL;
- break;
-
- case 'R':
- flags |= MU_LOCKER_RETRY;
- break;
-
- case 'T':
- flags |= MU_LOCKER_TIME;
- break;
-
- case 'P':
- flags |= MU_LOCKER_PID;
- break;
-
- default:
mu_error (_("invalid lock flag `%c'"), *s);
}
+ else if (*s == 'P')
+ {
+ /* TRANSLATORS: %c is replaced with the flag letter, and %s - with
+ the corresponding keyword. */
+ mu_diag_output (MU_DIAG_WARNING,
+ _("applying legacy flag %c, use %s instead"),
+ *s, kw);
+ flags |= MU_LOCKER_PID;
+ }
+ else
+ {
+ /* TRANSLATORS: %c is replaced with the flag letter, and %s - with
+ the corresponding keyword. */
+ mu_diag_output (MU_DIAG_WARNING,
+ _("ignoring legacy flag %c, use %s instead"),
+ *s, kw);
+ }
}
- mu_locker_set_default_flags (flags, mu_locker_assign);
+ if (flags)
+ mu_locker_set_default_flags (flags, mu_locker_assign);
return 0;
}
@@ -356,6 +366,8 @@ cb_locker_retry_timeout (void *data, mu_config_value_t *val)
mu_strerror (rc));
free (errmsg);
}
+ else if (t == 0)
+ mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_clear_bit);
else
{
mu_locker_set_default_retry_timeout (t);
@@ -380,6 +392,8 @@ cb_locker_retry_count (void *data, mu_config_value_t *val)
mu_strerror (rc));
free (errmsg);
}
+ else if (n == 0)
+ mu_locker_set_default_flags (MU_LOCKER_RETRY, mu_locker_clear_bit);
else
{
mu_locker_set_default_retry_count (n);
@@ -404,6 +418,8 @@ cb_locker_expire_timeout (void *data, mu_config_value_t *val)
mu_strerror (rc));
free (errmsg);
}
+ else if (t == 0)
+ mu_locker_set_default_flags (MU_LOCKER_TIME, mu_locker_clear_bit);
else
{
mu_locker_set_default_expire_timeout (t);
@@ -415,13 +431,39 @@ cb_locker_expire_timeout (void *data, mu_config_value_t *val)
static int
cb_locker_external (void *data, mu_config_value_t *val)
{
+ int t;
+
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
- mu_locker_set_default_external_program (val->v.string);
- mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_set_bit);
+ if (mu_str_to_c (val->v.string, mu_c_bool, &t, NULL) == 0 && t == 0)
+ {
+ mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_clear_bit);
+ }
+ else
+ {
+ mu_locker_set_default_external_program (val->v.string);
+ mu_locker_set_default_flags (MU_LOCKER_EXTERNAL, mu_locker_set_bit);
+ }
return 0;
}
+static int
+cb_locker_pid_check (void *data, mu_config_value_t *val)
+{
+ int t;
+
+ if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+ return 1;
+ if (mu_str_to_c (val->v.string, mu_c_bool, &t, NULL))
+ {
+ mu_error ("%s", _("not a boolean"));
+ return 1;
+ }
+ mu_locker_set_default_flags (MU_LOCKER_PID,
+ t ? mu_locker_set_bit : mu_locker_clear_bit);
+ return 0;
+}
+
static struct mu_cfg_param locking_cfg[] = {
/* FIXME: Flags are superfluous. */
{ "flags", mu_cfg_callback, NULL, 0, cb_locker_flags,
@@ -439,6 +481,9 @@ static struct mu_cfg_param locking_cfg[] = {
{ "external-locker", mu_cfg_callback, NULL, 0, cb_locker_external,
N_("Use external locker program."),
N_("prog: string") },
+ { "pid-check", mu_cfg_callback, NULL, 0, cb_locker_pid_check,
+ N_("Check if PID of the lock owner is active."),
+ N_("arg: bool") },
{ NULL, }
};
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 4a215ccb8..9c0497402 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -21,6 +21,7 @@ fsfolder
globtest
hdrcpy
imapio
+lck
listop
listsort
linetrack
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 6e82124de..13f513c9d 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -43,6 +43,7 @@ noinst_PROGRAMS = \
globtest\
hdrcpy\
imapio\
+ lck\
listop\
listsort\
linetrack\
@@ -120,6 +121,7 @@ TESTSUITE_AT += \
linecon.at\
list.at\
linetrack.at\
+ lock.at\
logstr.at\
mailcap.at\
mimehdr.at\
diff --git a/libmailutils/tests/lck.c b/libmailutils/tests/lck.c
new file mode 100644
index 000000000..fe7ac9213
--- /dev/null
+++ b/libmailutils/tests/lck.c
@@ -0,0 +1,335 @@
+/*
+ NAME
+ lck - mailutils locking test
+
+ SYNOPSIS
+ lck [-akpu?] [-e COMMAND] [-H SECONDS] [-r N] [-t SECONDS] [-x SECONDS]
+ [--abandon] [--delay=SECONDS] [--expire=SECONDS]
+ [--external=COMMAND] [--help] [--hold=SECONDS] [--kernel]
+ [--pid-check] [--retry=N] [--show-config-options] [--unlock]
+ [--usage] FILE
+
+ DESCRIPTION
+ Tests the mailutils locking mechanism. Unless --hold (-H) or --abandon
+ (-a) option is used, the tool locks the FILE and exits. If the --unlock
+ option is given, existing file lock is removed instead.
+
+ The --hold and --abandon options are used to simulate locking conflict
+ conditions. Both options cause lck to fork a child process, which
+ will attempt to lock the file using the same options as the main (master)
+ process. After obtaining the lock, the child notifies the master process
+ and, if --hold=N option was given, sleeps for N seconds before releasing
+ the lock. If the --abandon option is given, the lock is not released.
+ After that, the child terminates.
+
+ The master waits for child to successfully lock the file and attempts to
+ obtain the lock. If successful, it exits with the 0 status. On errors,
+ the termination status is 0.
+
+ OPTIONS
+ Locking type (default: dotlock):
+
+ -e, --external=COMMAND
+ Use the external locker command.
+
+ -k, --kernel
+ Use kernel locking (fnctl).
+
+ Locking parameters
+
+ -p, --pid-check
+ Check if the PID of lock owner is still active.
+
+ -r, --retry=N
+ Retry the lock N times.
+
+ -t, --delay=SECONDS
+ Delay between two successive locking attempts.
+
+ -x, --expire=SECONDS
+ Expire the lock after that many seconds.
+
+ Child operation modifiers
+
+ -a, --abandon
+ Abandon lock in child.
+
+ -H, --hold=SECONDS
+ Hold the lock for that many seconds.
+
+ Operation modifiers
+
+ -u, --unlock
+ Release the existing lock.
+
+ Informational options
+
+ --show-config-options
+ Show compilation options.
+
+ -?, --help
+ Give a short help list.
+
+ --usage
+ Give a short usage message.
+
+ AUTHOR
+ Sergey Poznyakoff <gray@gnu.org>
+
+ LICENSE
+ This program is part of GNU Mailutils testsuite.
+ Copyright (C) 2020-2021 Free Software Foundation, Inc.
+
+ GNU Mailutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Mailutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <mailutils/mailutils.h>
+
+static int flags = 0;
+static int unlock;
+static unsigned retry_count;
+static unsigned retry_sleep = 0;
+static int pid_check;
+static unsigned expire;
+static char const *extlocker;
+static unsigned hold_time;
+static int abandon_lock;
+
+static void
+cli_type (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
+{
+ switch (opt->opt_short)
+ {
+ case 'k':
+ flags = MU_LOCKER_OPTIONS (flags) | MU_LOCKER_KERNEL;
+ break;
+
+ case 'e':
+ flags = MU_LOCKER_OPTIONS (flags) | MU_LOCKER_EXTERNAL;
+ extlocker = arg;
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+struct mu_option options[] = {
+ MU_OPTION_GROUP ("Locking type (default: dotlock)"),
+
+ { "kernel", 'k', NULL, MU_OPTION_DEFAULT,
+ "use kernel locking", mu_c_void, NULL, cli_type },
+ { "external", 'e', "COMMAND", MU_OPTION_DEFAULT,
+ "use external locker command", mu_c_void, NULL, cli_type },
+
+ MU_OPTION_GROUP ("Locking parameters"),
+ { "retry", 'r', "N", MU_OPTION_DEFAULT,
+ "retry the lock N times",
+ mu_c_uint, &retry_count },
+ { "delay", 't', "SECONDS", MU_OPTION_DEFAULT,
+ "delay between two successive locking attempts (in seconds)",
+ mu_c_uint, &retry_sleep },
+ { "pid-check", 'p', NULL, MU_OPTION_DEFAULT,
+ "check if the PID of lock owner is still active",
+ mu_c_bool, &pid_check },
+ { "expire", 'x', "SECONDS", MU_OPTION_DEFAULT,
+ "expire the lock after that many seconds",
+ mu_c_uint, &expire },
+
+ MU_OPTION_GROUP ("Child operation modifiers"),
+ { "hold", 'H', "SECONDS", MU_OPTION_DEFAULT,
+ "hold lock for that many seconds",
+ mu_c_uint, &hold_time },
+ { "abandon",'a', NULL, MU_OPTION_DEFAULT,
+ "abandon lock in child",
+ mu_c_bool, &abandon_lock },
+
+ MU_OPTION_GROUP ("Operation modifiers"),
+ { "unlock", 'u', NULL, MU_OPTION_DEFAULT,
+ "unlock", mu_c_bool, &unlock },
+ MU_OPTION_END
+};
+
+static pid_t child_pid;
+static int child_status;
+static int time_out;
+
+void
+sighan (int sig)
+{
+ switch (sig)
+ {
+ case SIGCHLD:
+ if (waitpid (child_pid, &child_status, WNOHANG) == child_pid)
+ child_pid = 0;
+ break;
+
+ case SIGALRM:
+ time_out = 1;
+ break;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ mu_locker_t lck;
+ char const *file;
+ int rc;
+
+ mu_cli_simple (argc, argv,
+ MU_CLI_OPTION_OPTIONS, options,
+ MU_CLI_OPTION_PROG_DOC, "locking test tool",
+ MU_CLI_OPTION_PROG_ARGS, "FILE",
+ MU_CLI_OPTION_RETURN_ARGC, &argc,
+ MU_CLI_OPTION_RETURN_ARGV, &argv,
+ MU_CLI_OPTION_END);
+
+ if (argc != 1)
+ {
+ mu_error ("bad arguments; try %s --help for more info", mu_program_name);
+ return 1;
+ }
+ file = argv[0];
+
+ if (expire)
+ flags |= MU_LOCKER_TIME;
+ if (retry_count || retry_sleep)
+ flags |= MU_LOCKER_RETRY;
+ if (pid_check)
+ flags |= MU_LOCKER_PID;
+
+ MU_ASSERT (mu_locker_create (&lck, file, flags));
+ if (expire)
+ mu_locker_set_expire_time (lck, expire);
+ if (retry_count)
+ mu_locker_set_retries (lck, retry_count);
+ if (retry_sleep)
+ mu_locker_set_retry_sleep (lck, retry_sleep);
+ if (extlocker)
+ mu_locker_set_external (lck, extlocker);
+
+ if (hold_time || abandon_lock)
+ {
+ FILE *fp;
+ int p[2];
+
+ signal (SIGCHLD, sighan);
+ if (pipe (p))
+ {
+ mu_diag_funcall (MU_DIAG_CRIT, "pipe", NULL, errno);
+ return 1;
+ }
+
+ child_pid = fork ();
+ if (child_pid == -1)
+ {
+ mu_diag_funcall (MU_DIAG_CRIT, "fork", NULL, errno);
+ return 1;
+ }
+
+ if (child_pid == 0)
+ {
+ /* child */
+ signal (SIGCHLD, SIG_IGN);
+
+ fp = fdopen (p[1], "w");
+ close (p[0]);
+
+ rc = mu_locker_lock (lck);
+ fprintf (fp, "L%d\n", rc);
+ fclose (fp);
+ if (rc)
+ abort ();
+ if (hold_time)
+ sleep (hold_time);
+ if (abandon_lock)
+ rc = 0;
+ else
+ rc = mu_locker_remove_lock (lck);
+ exit (rc != 0);
+ }
+
+ /* master */
+ fp = fdopen (p[0], "r");
+ close (p[1]);
+
+ signal (SIGALRM, sighan);
+ alarm (5);
+ if (fscanf (fp, "L%d", &rc) != 1)
+ {
+ if (time_out)
+ mu_error ("child didn't respond");
+ else
+ mu_error ("bad response from child");
+ if (child_pid)
+ kill (child_pid, SIGKILL);
+ return 1;
+ }
+ alarm (0);
+
+ if (rc)
+ {
+ mu_error ("child lock failed");
+ if (child_pid)
+ kill (child_pid, SIGKILL);
+ return 1;
+ }
+ }
+
+ if (unlock)
+ rc = mu_locker_remove_lock (lck);
+ else
+ rc = mu_locker_lock (lck);
+ if (rc)
+ mu_diag_funcall (MU_DIAG_ERROR,
+ unlock ? "mu_locker_remove_lock" : "mu_locker_lock",
+ NULL, rc);
+
+ if (child_pid > 0)
+ {
+ if (waitpid (child_pid, &child_status, WNOHANG) != child_pid)
+ {
+ if (child_pid)
+ kill (child_pid, SIGKILL);
+ waitpid (child_pid, &child_status, 0);
+ child_status = 0;
+ }
+ }
+
+ if (WIFEXITED (child_status))
+ {
+ int status = WEXITSTATUS (child_status);
+ if (status != 0)
+ {
+ mu_error ("child terminated with status %d", status);
+ return 1;
+ }
+ }
+ else if (WIFSIGNALED (child_status))
+ {
+ mu_error ("child terminated on signal %d", WTERMSIG (child_status));
+ return 1;
+ }
+ else
+ {
+ mu_error ("child terminated with unhandled status %d", child_status);
+ return 1;
+ }
+
+ return rc != 0;
+}
diff --git a/libmailutils/tests/lock.at b/libmailutils/tests/lock.at
new file mode 100644
index 000000000..0886390b9
--- /dev/null
+++ b/libmailutils/tests/lock.at
@@ -0,0 +1,59 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2010-2021 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# GNU Mailutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+AT_BANNER([Locking])
+
+m4_pushdef([LCK_TEST],[
+AT_SETUP([$1])
+AT_KEYWORDS([lock])
+AT_CHECK([touch file
+lck $2 file
+],
+m4_shift2($@))
+AT_CLEANUP
+])
+
+# Child holds lock for 4 seconds, master acquires it when child has
+# released it.
+LCK_TEST([retries], [--hold=4 --retry=10 --delay=1])
+
+# Child holds lock for 4 seconds, master does two retries with one
+# second interval and finishes before being able to acquire it.
+LCK_TEST([conflict with previous locker], [--hold=4 --retry=2 --delay=1],
+ [1],[],
+ [lck: mu_locker_lock() failed: Conflict with previous locker
+])
+
+# Child abandons the lock; master is not able to acquire it.
+LCK_TEST([abandoned lock], [--abandon --retry=4 --delay=1],
+ [1],[],
+ [lck: mu_locker_lock() failed: Conflict with previous locker
+])
+
+# Child abandons the lock; master asserts that its pid is not active and
+# acquires it.
+LCK_TEST([PID check],[--pid-check --abandon --retry=4 --delay=1])
+
+# Child abandons the lock; master waits until it has expired and acquires
+# it.
+LCK_TEST([lock expiration],
+ [--abandon --expire=3 --retry=10 --delay=1])
+
+
+# Default settings correspond to --retry=10 --delay=1 --expire=600
+LCK_TEST([default settings], [--hold=2])
+
+m4_popdef([LCK_TEST])
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 1e4f5dd98..915d00171 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -257,6 +257,8 @@ m4_include([msgset.at])
m4_include([globtest.at])
m4_include([linetrack.at])
+
+m4_include([lock.at])
m4_popdef([MU_TEST_GROUP])
m4_popdef([MU_TEST_KEYWORDS])

Return to:

Send suggestions and report system problems to the System administrator.