zsh-workers
 help / color / mirror / code / Atom feed
From: Cedric Ware <cedric.ware__bml@normalesup.org>
To: "zsh-workers@zsh.org" <zsh-workers@zsh.org>
Subject: Re: [PATCH] Enable sub-second timeout in zsystem flock
Date: Sat, 4 Jan 2020 19:47:34 +0100	[thread overview]
Message-ID: <20200104184734.ienw42rwq2xu6aap@phare.normalesup.org> (raw)
In-Reply-To: <CAH+w=7brN4fjpbiwU2CGOdRG4sHXNijYf5v4Qzypa9mk5WaQtA@mail.gmail.com>


	Hello,

This is a re-send/update of a patch I'd proposed some time ago
(see http://www.zsh.org/mla/workers/2019/msg00620.html), to allow a
sub-second granularity for the zsystem flock function's timeout in the
zsh/system module.  This version of the patch is against 5.7.1-test-2,
and also updates the documentation in Doc/Zsh/mod_system.yo .

At the time, I'd been answered:

Bart Schaefer (Monday 2019-07-29):
> In future, please either inline patches or attach them as text/plain
> (e.g. with a ".txt" extension instead of ".patch").  Thanks!

Sure, please find it at the end of this mail.

> > implement this timeout: set a timer such as setitimer(2) which sends
> > a SIGALRM on timeout
> 
> Unfortunately that technique can't be used because ALRM is a signal
> that the user is allowed to trap via the "trap" command or TRAPALRM
> function, and which is controlled by the TMOUT variable which is also
> user settable.

Indeed, I see now.  But, to be clear, I didn't use that technique here.
That was just speculation.  With this patch, the function still polls
the lock periodically as before, except now the period can be specified
instead of being hardcoded to 1 second.

Also, I did some testing, but only checked that invoking zsystem flock
with various values for -t and -p seemed to do what I intended.
Is there a more rigorous test framework for this kind of thing, or
anything else to be done that might help this patch be included?

					Thanks, best regards,
					Cedric Ware.


diff -ru zsh-5.7.1-test-2.orig/Doc/Zsh/mod_system.yo zsh-5.7.1-test-2/Doc/Zsh/mod_system.yo
--- zsh-5.7.1-test-2.orig/Doc/Zsh/mod_system.yo	2019-08-17 23:14:27.000000000 +0200
+++ zsh-5.7.1-test-2/Doc/Zsh/mod_system.yo	2020-01-03 21:12:34.623024717 +0100
@@ -196,9 +196,10 @@
 
 By default the shell waits indefinitely for the lock to succeed.
 The option tt(-t) var(timeout) specifies a timeout for the lock in
-seconds; currently this must be an integer.  The shell will attempt
-to lock the file once a second during this period.  If the attempt
-times out, status 2 is returned.
+seconds; fractional seconds are allowed.  The shell will attempt
+to lock the file every var(period) seconds during this period:
+once a second by default, or according to the  value set by option
+tt(-p).  If the attempt times out, status 2 is returned.
 
 If the option tt(-e) is given, the file descriptor for the lock is
 preserved when the shell uses tt(exec) to start a new process;
diff -ru zsh-5.7.1-test-2.orig/Src/Modules/system.c zsh-5.7.1-test-2/Src/Modules/system.c
--- zsh-5.7.1-test-2.orig/Src/Modules/system.c	2019-08-17 23:14:27.000000000 +0200
+++ zsh-5.7.1-test-2/Src/Modules/system.c	2020-01-03 21:13:34.019588503 +0100
@@ -532,6 +532,8 @@
 {
     int cloexec = 1, unlock = 0, readlock = 0;
     zlong timeout = -1;
+    long timeout_retry = 1e6;
+    mnumber timeout_param;
     char *fdvar = NULL;
 #ifdef HAVE_FCNTL_H
     struct flock lck;
@@ -583,7 +585,35 @@
 		} else {
 		    optarg = *args++;
 		}
-		timeout = mathevali(optarg);
+		timeout_param = matheval(optarg);
+		if (!(timeout_param.type & MN_FLOAT)) {
+		    timeout_param.type = MN_FLOAT;
+		    timeout_param.u.d = (double)timeout_param.u.l;
+		}
+		timeout = (zlong)(timeout_param.u.d * 1e6);
+		break;
+
+	    case 'p':
+		/* retry period in seconds */
+		if (optptr[1]) {
+		    optarg = optptr + 1;
+		    optptr += strlen(optarg) - 1;
+		} else if (!*args) {
+		    zwarnnam(nam,
+			     "flock: option %c requires a numeric retry period",
+			     opt);
+		    return 1;
+		} else {
+		    optarg = *args++;
+		}
+		timeout_param = matheval(optarg);
+		if (!(timeout_param.type & MN_FLOAT)) {
+		    timeout_param.type = MN_FLOAT;
+		    timeout_param.u.d = (double)timeout_param.u.l;
+		}
+		zlong timeout_retry_tmp = timeout_param.u.d * 1e6;
+		timeout_retry = (timeout_retry_tmp > LONG_MAX) ?
+		    LONG_MAX : timeout_retry_tmp;
 		break;
 
 	    case 'u':
@@ -647,7 +677,7 @@
     lck.l_len = 0;  /* lock the whole file */
 
     if (timeout > 0) {
-	time_t end = time(NULL) + (time_t)timeout;
+	zlong end = time_clock_us() + timeout;
 	while (fcntl(flock_fd, F_SETLK, &lck) < 0) {
 	    if (errflag) {
                 zclose(flock_fd);
@@ -658,11 +688,15 @@
 		zwarnnam(nam, "failed to lock file %s: %e", args[0], errno);
 		return 1;
 	    }
-	    if (time(NULL) >= end) {
+	    zlong now = time_clock_us();
+	    if (now >= end) {
                 zclose(flock_fd);
 		return 2;
             }
-	    sleep(1);
+	    if (now + timeout_retry > end) {
+		timeout_retry = end - now;
+	    }
+	    zsleep(timeout_retry);
 	}
     } else {
 	while (fcntl(flock_fd, timeout == 0 ? F_SETLK : F_SETLKW, &lck) < 0) {
diff -ru zsh-5.7.1-test-2.orig/Src/utils.c zsh-5.7.1-test-2/Src/utils.c
--- zsh-5.7.1-test-2.orig/Src/utils.c	2019-12-21 09:29:14.000000000 +0100
+++ zsh-5.7.1-test-2/Src/utils.c	2020-01-03 21:13:34.023588812 +0100
@@ -2749,6 +2749,26 @@
 }
 
 /*
+ * Return the current time in microseconds, using the system's
+ * monotonic clock if supported, the wall clock if not.
+ */
+
+/**/
+zlong
+time_clock_us(void)
+{
+#if defined(HAS_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * (zlong)1e6 + ts.tv_nsec / 1000;
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return tv.tv_sec * (zlong)1e6 + tv.tv_usec;
+#endif
+}
+
+/*
  * Sleep for the given number of microseconds --- must be within
  * range of a long at the moment, but this is only used for
  * limited internal purposes.

  reply	other threads:[~2020-01-04 21:05 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-29 20:35 Cedric Ware
2019-07-29 22:25 ` Bart Schaefer
2020-01-04 18:47   ` Cedric Ware [this message]
2020-01-05 18:42     ` dana
2020-01-05 21:49       ` dana
2020-01-06 17:30       ` Cedric Ware
2020-01-06 17:36         ` Peter Stephenson
2020-01-07  3:48         ` dana
2020-01-11 15:41           ` Cedric Ware
2020-01-11 19:36             ` dana
2020-01-12  4:25               ` dana
2020-03-08 18:39                 ` Cedric Ware
2020-03-12 18:46                   ` dana
2020-03-12 19:13                     ` dana
2020-03-14 21:04                     ` Cedric Ware
2020-03-15  0:50                       ` Daniel Shahaf
2020-03-15  1:04                         ` dana
2020-03-15 16:03                         ` Cedric Ware
2020-03-15 16:54                           ` Daniel Shahaf
2020-03-15 17:35                             ` Peter Stephenson
2020-03-15 18:36                             ` Cedric Ware
2020-03-15 19:13                               ` Daniel Shahaf
2020-04-13 21:34                             ` Cedric Ware
2020-04-14 11:47                               ` Daniel Shahaf
2020-04-14 20:21                                 ` Cedric Ware
2020-04-15  1:15                                   ` Daniel Shahaf
2020-04-15  2:05                                     ` dana
2020-04-16  4:24                                       ` Daniel Shahaf
2020-04-18 16:32                                         ` Cedric Ware
2020-04-20 17:28                                           ` dana
2020-04-20 22:17                                             ` Cedric Ware
2020-03-15  1:04                       ` Daniel Shahaf
2020-03-13 14:26                   ` dana

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200104184734.ienw42rwq2xu6aap@phare.normalesup.org \
    --to=cedric.ware__bml@normalesup.org \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).