[Sun Java 1.4.2] Sun's Java tryLock() error return with HP-UX NFS served disks

SYMPTOM/SOLUTION TEMPLATE:
PRODUCT: Sun's Java 1.4.2-* GNU Java 1.4.2 OP/SYS: Sun Solaris 8 Fedora Core 4
COMPONENT: HP-UX NFS Server
SOURCE: Philippe Vouters Fontainebleau/France
HIGH QUALITY MOBILES+TABLETS: http://android-land.fr
SYMPTOM(S) or PROBLEM(S): A tryLock() (without any argument) to lock an entire file returns, when the file resides on a HP-UX served NFS disk: java.io.IOException: No record locks available When the file is located on a Sun's computer, no error is returned.
HEWLETT-PACKARD RESPONSE: The "No record locks available" corresponds to a ENOLCK error return from the Java run-time used fcntl function, as per a "truss -v all" on the corresponding Java program execution. Sun programs the fcntl function with a l_len flock structure parameter to minus one instead of Sun's documented zero. This is illegal on HP-UX. So this is clearly a bug inside Sun's Java Runtime Environment (JRE).
ALTERNATIVE: Use the alternate tryLock Java function with arguments to lock the entire file. The alternate tryLock has three arguments. tryLock (int poistion, int size, boolean shared).
ANALYSIS: A "truss -v all" taken on a Solaris system reveals the following: fcntl(5, F_SETLK64, 0xF96815C8) Err#46 ENOLCK typ=F_WRLCK whence=SEEK_SET start=0 len=-1 sys=859040 pid=0 lwp_sema_wait(0xF9581E60) = 0 sema type: USYNC_PROCESS count = 0 open("/usr/dt/lib/nls/msg/C/SUNW_OST_OSLIB.cat", O_RDONLY) Err#2 ENOENT open("/usr/lib/locale/C/LC_MESSAGES/SUNW_OST_OSLIB.mo", O_RDONLY) Err#2 ENOENT write(2, " j a v a . i o . I O E x".., 46) = 46 write(2, "\n", 1) = 1 write(2, "\t a t s u n . n i o .".., 51) = 51 write(2, "\n", 1) = 1 The len=-1 to lock the entire file on the fcntl is not advised according to Sun's fcntl man which states the following, regarding the correct setting of the flock structure: The flock structure contains at least the following ele- ments: short l_type; /* lock operation type */ short l_whence; /* lock base indicator */ off_t l_start; /* starting offset from base */ off_t l_len; /* lock length; l_len == 0 means until end of file */ long l_sysid; /* system ID running process holding lock */ pid_t l_pid; /* process ID of process holding lock */ According this man, the l_len parameter should have been set to zero, instead of minus one. It should be also noted that an incorrect setting of l_len to -1 on a Sun's computer is not checked and does not fail with an illegal parameter, contrary to what happens on a HP-UX computer. Therefore there are two problems here: 1/ incorrect setting of l_len to -1 by Sun's JRE. 2/ incorrect argument not checked and discarded by Sun's C run-time library. A similar problem ought to occur for the same Java program when the file is directed to a HP-UX NFS disk when this Java program is executed on Linux using GNU Java 1.4.2. Under Fedora Core 4, which is the latest home version of Red Hat Linux, the command: $ strace -v -e trace=all -f -o Locking.txt java Locking . true reveals that GNU Java uses the following function in its implementation of tryLock(): 3134 fcntl64(11, F_SETLK64, {type=F_UNLCK, whence=SEEK_SET, start=0, len=9223372036854775807}, 0xb721c93c) = 0 3134 write(1, "Closing channel 0\n", 18) = 18 where the len value is LONG_MAX, whereas the reading of /usr/include/bits/fcntl.h indicates for the flock or flock64 structure assignments: struct flock { short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ #ifndef __USE_FILE_OFFSET64 __off_t l_start; /* Offset where the lock begins. */ __off_t l_len; /* Size of the locked area; zero means until EOF. */ #else __off64_t l_start; /* Offset where the lock begins. */ __off64_t l_len; /* Size of the locked area; zero means until EOF. */ #endif __pid_t l_pid; /* Process holding the lock. */ }; #ifdef __USE_LARGEFILE64 struct flock64 { short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ __off64_t l_start; /* Offset where the lock begins. */ __off64_t l_len; /* Size of the locked area; zero means until EOF. */ __pid_t l_pid; /* Process holding the lock. */ }; #endif Therefore Fedora Core 4 (FC4) should have set its l_len parameter to zero to lock until EOF, which it does not. So FC4 ought to work with Sun's NFS disks, but not with HP-UX NFS disks.
REPRODUCER C PROGRAM: #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <errno.h> int main( int argc, char **argv ) { int fd; struct flock64 sflock; memset(&sflock,0,sizeof(sflock)); sflock.l_type=F_WRLCK; sflock.l_whence=SEEK_SET; sflock.l_start=0; /* Lock entire file until its end */ #ifdef LIKE_SUNS_JAVA_1_4_2 sflock.l_len=-1; #else sflock.l_len=0; #endif printf("Locking file %s ....\n", argv[1] ); if ((fd=open(argv[1], O_CREAT|O_RDWR|O_LARGEFILE, 0666)) == -1) { printf("Cannot open file %s: %s\n", argv[1],strerror(errno)); exit(-1); } if((fcntl(fd,F_SETLK64,&sflock)) == -1) { perror("Error locking"); exit(-1); } printf(" File %s locked ...\n", argv[1] ); getchar(); sflock.l_type=F_UNLCK; if((fcntl(fd,F_SETLK64,&sflock)) == -1) { perror("Error unlocking"); exit(-1); } close(fd); printf("File %s unlocked ....\n", argv[1] ); return 0; }
REFERENCE(S): man truss on Sun and strace on Linux. man fcntl and /usr/include/bits/fcntl.h on FC4.