aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2019-07-29 13:28:31 +1000
committerSteve Bennett <steveb@workware.net.au>2019-07-31 08:46:01 +1000
commitc8abda4d473268842201f228b8980e523766e91b (patch)
treee8563fd0694c51885bf0e4f504049c55c50e0f41
parenta8b8c416c7f3c9e06fe3320b25e8dd37570e9f92 (diff)
downloadjimtcl-c8abda4d473268842201f228b8980e523766e91b.zip
jimtcl-c8abda4d473268842201f228b8980e523766e91b.tar.gz
jimtcl-c8abda4d473268842201f228b8980e523766e91b.tar.bz2
aio: Add support for lock -wait
Sometimes it is useful to wait for a lock to become available. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim-aio.c16
-rw-r--r--jim_tcl.txt20
-rw-r--r--tests/lock.test13
3 files changed, 36 insertions, 13 deletions
diff --git a/jim-aio.c b/jim-aio.c
index ba8216f..a5fa24e 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -1440,13 +1440,21 @@ static int aio_cmd_lock(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
struct flock fl;
+ int lockmode = F_SETLK;
+
+ if (argc == 1) {
+ if (!Jim_CompareStringImmediate(interp, argv[0], "-wait")) {
+ return -1;
+ }
+ lockmode = F_SETLKW;
+ }
fl.l_start = 0;
fl.l_len = 0;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
- switch (fcntl(af->fd, F_SETLK, &fl))
+ switch (fcntl(af->fd, lockmode, &fl))
{
case 0:
Jim_SetResultInt(interp, 1);
@@ -1732,12 +1740,12 @@ static const jim_subcmd_type aio_command_table[] = {
},
#endif
#if defined(HAVE_STRUCT_FLOCK)
- { "lock",
+ { "lock ?-wait?",
NULL,
aio_cmd_lock,
0,
- 0,
- /* Description: Attempt to get a lock. */
+ 1,
+ /* Description: Attempt to get a lock, possibly waiting */
},
{ "unlock",
NULL,
diff --git a/jim_tcl.txt b/jim_tcl.txt
index 77c4b35..247ad7e 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -56,6 +56,7 @@ Changes since 0.78
~~~~~~~~~~~~~~~~~~
1. Add `file mtimeus` for high resolution file timestamps
2. `aio` now supports datagram Unix-Domain sockets
+3. Add support for `aio lock -wait`
Changes between 0.77 and 0.78
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4581,9 +4582,9 @@ aio
+$handle *buffering none|line|full*+::
Sets the buffering mode of the stream.
-+$handle *close* ?r(ead)|w(rite)|-nodelete?+::
++$handle *close ?r(ead)|w(rite)|-nodelete?*+::
Closes the stream.
- The +'read'+ and +'write'+ arguments perform a "half-close" on a socket. See the +shutdown(2)+ man page.
+ The +'read'+ and +'write'+ arguments perform a "half-close" on a socket. See the 'shutdown(2)' man page.
The +'-nodelete'+ option is applicable only for Unix domain sockets. It closes the socket
but does not delete the bound path (e.g. after `os.fork`).
@@ -4609,9 +4610,10 @@ aio
+$handle *isatty*+::
Returns 1 if the stream is a tty device.
-+$handle *lock*+::
++$handle *lock ?-wait?*+::
Apply a POSIX lock to the open file associated with the handle using
- fcntl(2).
+ 'fcntl(F_SETLK)', or 'fcntl(F_SETLKW)' to wait for the lock to be available if +'-wait'+
+ is specified.
The handle must be open for write access.
Returns 1 if the lock was successfully obtained, 0 otherwise.
An error occurs if the handle is not suitable for locking (e.g.
@@ -4641,7 +4643,7 @@ aio
Seeks in the stream (default 'current')
+$handle *sendto* 'str ?address'+::
- Sends the string, +'str'+, to the given address (host:port or path) via the socket using sendto(2).
+ Sends the string, +'str'+, to the given address (host:port or path) via the socket using 'sendto(2)'.
This is intended for udp/dgram sockets and may give an error or behave in unintended
ways for other handle types.
Returns the number of bytes written.
@@ -4657,8 +4659,8 @@ aio
integer socket options: +sndbuf, rcvbuf+
+$handle *sync*+::
- Flush the stream, then fsync(2) to commit any changes to storage.
- Only available on platforms that support fsync(2).
+ Flush the stream, then 'fsync(2)' to commit any changes to storage.
+ Only available on platforms that support 'fsync(2)'.
+$handle *tell*+::
Returns the current seek position
@@ -4668,7 +4670,7 @@ aio
If arguments are given, they must either be a dictionary, or +setting value \...+
Abbrevations are supported for both settings and values, so the following is acceptable:
+$f tty parity e input c out raw+.
- Only available on platforms that support termios(3). Supported settings are:
+ Only available on platforms that support 'termios(3)'. Supported settings are:
+*baud* 'rate'+;;
Baud rate. e.g. 115200
@@ -4698,7 +4700,7 @@ aio
+*vtime* 'time'+;;
Timeout for noncanonical read (units of 0.1 seconds)
-+$handle *ssl* *?-server cert priv?*+::
++$handle *ssl* ?*-server* 'cert priv'?+::
Upgrades the stream to a SSL/TLS session and returns the handle.
+$handle *unlock*+::
diff --git a/tests/lock.test b/tests/lock.test
index 3672d6a..e7b0b2d 100644
--- a/tests/lock.test
+++ b/tests/lock.test
@@ -42,6 +42,19 @@ test lock-1.5 {grab lock from sub-process} {
set stat
} 0
+test lock-1.6 {wait for lock} {
+ # Run a child process that grabs the lock for 0.5 seconds
+ set pid [exec [info nameofexecutable] -e {set fh [open locktest.file r+]; $fh lock; sleep 0.5} >/dev/null &]
+ # And wait to acquire the lock in the parent. Should take ~500ms
+ set start [clock millis]
+ sleep 0.1
+ $fh lock -wait
+ set delta [expr {[clock millis] - $start}]
+ if {$delta < 100} {
+ error "Lock acquired after ${delta}ms"
+ }
+} {}
+
$fh close
file delete locktest.file