flock: add --verbose option

Jenkins script jobs using flock are a great example of a situation in
which one may want an automation to be verbose, so that when unexpected
events happen there is more hints in logs.

Reviewed-by: Benno Schulenberg <bensberg@justemail.net>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2015-02-07 23:45:24 +00:00
parent a3d29ee0c7
commit 59dc9f28b5
3 changed files with 35 additions and 4 deletions

View File

@ -1,8 +1,8 @@
if BUILD_FLOCK if BUILD_FLOCK
usrbin_exec_PROGRAMS += flock usrbin_exec_PROGRAMS += flock
dist_man_MANS += sys-utils/flock.1 dist_man_MANS += sys-utils/flock.1
flock_SOURCES = sys-utils/flock.c flock_SOURCES = sys-utils/flock.c lib/monotonic.c
flock_LDADD = $(LDADD) libcommon.la flock_LDADD = $(LDADD) libcommon.la $(CLOCKGETTIME_LIBS)
endif endif
if BUILD_IPCMK if BUILD_IPCMK

View File

@ -107,6 +107,10 @@ option for the exit code used. The zero number of
.IR seconds .IR seconds
is interpreted as \fB\-\-nonblock\fR. is interpreted as \fB\-\-nonblock\fR.
.TP .TP
.B \-\-verbose
Report how long it took to acquire the lock, or why the lock could not be
obtained.
.TP
.BR \-V , " \-\-version" .BR \-V , " \-\-version"
Display version information and exit. Display version information and exit.
.TP .TP

View File

@ -44,6 +44,7 @@
#include "strutils.h" #include "strutils.h"
#include "closestream.h" #include "closestream.h"
#include "timer.h" #include "timer.h"
#include "monotonic.h"
static void __attribute__((__noreturn__)) usage(int ex) static void __attribute__((__noreturn__)) usage(int ex)
{ {
@ -66,6 +67,7 @@ static void __attribute__((__noreturn__)) usage(int ex)
fputs(_( " -E, --conflict-exit-code <number> exit code after conflict or timeout\n"), stderr); fputs(_( " -E, --conflict-exit-code <number> exit code after conflict or timeout\n"), stderr);
fputs(_( " -o, --close close file descriptor before running command\n"), stderr); fputs(_( " -o, --close close file descriptor before running command\n"), stderr);
fputs(_( " -c, --command <command> run a single command string through the shell\n"), stderr); fputs(_( " -c, --command <command> run a single command string through the shell\n"), stderr);
fputs(_( " --verbose increase verbosity\n"), stderr);
fprintf(stderr, USAGE_SEPARATOR); fprintf(stderr, USAGE_SEPARATOR);
fprintf(stderr, USAGE_HELP); fprintf(stderr, USAGE_HELP);
fprintf(stderr, USAGE_VERSION); fprintf(stderr, USAGE_VERSION);
@ -120,6 +122,8 @@ int main(int argc, char *argv[])
int opt, ix; int opt, ix;
int do_close = 0; int do_close = 0;
int status; int status;
int verbose = 0;
struct timeval time_start, time_done;
/* /*
* The default exit code for lock conflict or timeout * The default exit code for lock conflict or timeout
* is specified in man flock.1 * is specified in man flock.1
@ -128,7 +132,9 @@ int main(int argc, char *argv[])
char **cmd_argv = NULL, *sh_c_argv[4]; char **cmd_argv = NULL, *sh_c_argv[4];
const char *filename = NULL; const char *filename = NULL;
struct sigaction old_sa; struct sigaction old_sa;
enum {
OPT_VERBOSE = CHAR_MAX + 1
};
static const struct option long_options[] = { static const struct option long_options[] = {
{"shared", no_argument, NULL, 's'}, {"shared", no_argument, NULL, 's'},
{"exclusive", no_argument, NULL, 'x'}, {"exclusive", no_argument, NULL, 'x'},
@ -139,6 +145,7 @@ int main(int argc, char *argv[])
{"wait", required_argument, NULL, 'w'}, {"wait", required_argument, NULL, 'w'},
{"conflict-exit-code", required_argument, NULL, 'E'}, {"conflict-exit-code", required_argument, NULL, 'E'},
{"close", no_argument, NULL, 'o'}, {"close", no_argument, NULL, 'o'},
{"verbose", no_argument, NULL, OPT_VERBOSE},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@ -184,6 +191,9 @@ int main(int argc, char *argv[])
conflict_exit_code = strtos32_or_err(optarg, conflict_exit_code = strtos32_or_err(optarg,
_("invalid exit code")); _("invalid exit code"));
break; break;
case OPT_VERBOSE:
verbose = 1;
break;
case 'V': case 'V':
printf(UTIL_LINUX_VERSION); printf(UTIL_LINUX_VERSION);
exit(EX_OK); exit(EX_OK);
@ -239,16 +249,23 @@ int main(int argc, char *argv[])
setup_timer(&timeout, &old_timer, &old_sa, timeout_handler); setup_timer(&timeout, &old_timer, &old_sa, timeout_handler);
} }
if (verbose)
gettime_monotonic(&time_start);
while (flock(fd, type | block)) { while (flock(fd, type | block)) {
switch (errno) { switch (errno) {
case EWOULDBLOCK: case EWOULDBLOCK:
/* -n option set and failed to lock. */ /* -n option set and failed to lock. */
if (verbose)
warnx(_("failed to get lock"));
exit(conflict_exit_code); exit(conflict_exit_code);
case EINTR: case EINTR:
/* Signal received */ /* Signal received */
if (timeout_expired) if (timeout_expired) {
/* -w option set and failed to lock. */ /* -w option set and failed to lock. */
if (verbose)
warnx(_("timeout while waiting to get lock"));
exit(conflict_exit_code); exit(conflict_exit_code);
}
/* otherwise try again */ /* otherwise try again */
continue; continue;
case EIO: case EIO:
@ -282,13 +299,23 @@ int main(int argc, char *argv[])
if (have_timeout) if (have_timeout)
cancel_timer(&old_timer, &old_sa); cancel_timer(&old_timer, &old_sa);
if (verbose) {
struct timeval delta;
gettime_monotonic(&time_done);
timersub(&time_done, &time_start, &delta);
printf(_("%s: getting lock took %ld.%06ld seconds\n"),
program_invocation_short_name, delta.tv_sec,
delta.tv_usec);
}
status = EX_OK; status = EX_OK;
if (cmd_argv) { if (cmd_argv) {
pid_t w, f; pid_t w, f;
/* Clear any inherited settings */ /* Clear any inherited settings */
signal(SIGCHLD, SIG_DFL); signal(SIGCHLD, SIG_DFL);
if (verbose)
printf(_("%s: executing %s\n"), program_invocation_short_name, cmd_argv[2]);
f = fork(); f = fork();
if (f < 0) { if (f < 0) {