diff options
author | HummyPkg <af123@hummypkg.org.uk> | 2016-08-19 08:45:08 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2016-08-20 11:01:10 +1000 |
commit | dc7c2751eb01e8aa37740ce494e2857ce11b5ad3 (patch) | |
tree | 96ca0096c0182b7de179249246b3ecad0aa40d70 | |
parent | 278003ca94cf3d3e5f9619e6b2fd08ab590c0899 (diff) | |
download | jimtcl-dc7c2751eb01e8aa37740ce494e2857ce11b5ad3.zip jimtcl-dc7c2751eb01e8aa37740ce494e2857ce11b5ad3.tar.gz jimtcl-dc7c2751eb01e8aa37740ce494e2857ce11b5ad3.tar.bz2 |
add POSIX lock/unlock methods to aio objects
-rw-r--r-- | jim-aio.c | 51 | ||||
-rw-r--r-- | jim_tcl.txt | 12 | ||||
-rw-r--r-- | tests/lock.test | 60 |
3 files changed, 123 insertions, 0 deletions
@@ -1159,6 +1159,43 @@ static int aio_cmd_verify(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } #endif /* JIM_BOOTSTRAP */ +static int aio_cmd_lock(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + struct flock fl = { F_WRLCK, SEEK_SET, 0, 0 }; + + switch (fcntl(af->fd, F_SETLK, &fl)) + { + case 0: + Jim_SetResultInt(interp, 1); + break; + case -1: + if (errno == EACCES || errno == EAGAIN) + Jim_SetResultInt(interp, 0); + else + { + Jim_SetResultFormatted(interp, "lock failed: %s", + strerror(errno)); + return JIM_ERR; + } + break; + default: + Jim_SetResultInt(interp, 0); + break; + } + + return JIM_OK; +} + +static int aio_cmd_unlock(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + struct flock fl = { F_UNLCK, SEEK_SET, 0, 0 }; + + Jim_SetResultInt(interp, fcntl(af->fd, F_SETLK, &fl) == 0); + return JIM_OK; +} + static const jim_subcmd_type aio_command_table[] = { { "read", "?-nonewline? ?len?", @@ -1333,6 +1370,20 @@ static const jim_subcmd_type aio_command_table[] = { /* Description: Verifies the certificate of a SSL/TLS channel */ }, #endif /* JIM_BOOTSTRAP */ + { "lock", + NULL, + aio_cmd_lock, + 0, + 0, + /* Description: Attempt to get a lock. */ + }, + { "unlock", + NULL, + aio_cmd_unlock, + 0, + 0, + /* Description: Relase a lock. */ + }, { NULL } }; diff --git a/jim_tcl.txt b/jim_tcl.txt index 5c6e206..97dc83e 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -58,6 +58,7 @@ Changes between 0.76 and 0.77 3. Added `zlib` 4. Added support for boolean constants in `expr` 5. `string is` now supports 'boolean' class +6. Add support for `aio lock` and `aio unlock` Changes between 0.75 and 0.76 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4522,6 +4523,14 @@ aio +$handle *isatty*+:: Returns 1 if the stream is a tty device. ++$handle *lock*+:: + Apply a POSIX lock to the open file associated with the handle using + fcntl(2). + 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. + if it is not open for write) + +$handle *ndelay ?0|1?*+:: Set O_NDELAY (if arg). Returns current/new setting. Note that in general ANSI I/O interacts badly with non-blocking I/O. @@ -4558,6 +4567,9 @@ aio +$handle *ssl* *?-server cert priv?*+:: Initiates a SSL/TLS session and returns a new stream ++$handle *unlock*+:: + Release a POSIX lock previously acquired by `aio lock`. + +$handle *verify*+:: Verifies the certificate of a SSL/TLS stream peer diff --git a/tests/lock.test b/tests/lock.test new file mode 100644 index 0000000..2fe6ee4 --- /dev/null +++ b/tests/lock.test @@ -0,0 +1,60 @@ +# This test file covers POSIX file locking +# +# This file contains a collection of tests for one or more of the Tcl built-in +# commands. Sourcing this file into Tcl runs the tests and generates output +# for errors. No output means no errors were found. +# +# Copyright (c) 2003-2009 Donal K. Fellows +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. + +source [file dirname [info script]]/testing.tcl + +set fh [open locktest.file w] + +test lock-1.1 {grab lock} { + $fh lock +} 1 + +test lock-1.2 {grab lock again} { + $fh lock +} 1 + +test lock-1.j {release lock} { + $fh unlock +} 1 + +test lock-1.4 {release lock again} { + $fh unlock +} 1 + +test lock-1.5 {grab lock from sub-process} { + switch [set pid [os.fork]] { + -1 { error "Fork error." } + 0 { + # Child process + $fh lock + sleep 2 + puts $fh [$fh unlock] + exit + } + default { + sleep 1 + set stat [$fh lock] + set stat + } + } +} 0 + +# fcntl() allows unlock on non-held lock so unlock will always return 1 +#set x [os.wait $pid] +#test lock-1.6 {check unlock in child process} { +# $fh seek 0 start +# $fh read 1 +#} 1 + +$fh close +file delete locktest.file + +testreport + |