ken@sdd.hp.com (Ken Stone) (02/01/91)
A while back I heard several people asking about lockf for perl. Yea you certainly >can< do it with fcntl(2) but its kind of a pain if your used to having lockf at your disposal. So here is a patch that should drop into 3.0@41 or 3.0@44 and along with it is a new member of the test suite to test it out !! If anybody else thinks this is great ... maybe Larry would consider it for 4.0 .... please ??? -- Ken # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Source Hacker <src@hpsdlz> on Mon Jan 14 14:21:05 1991 # # This archive contains: # lockf.patches op.lockf # LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH echo x - lockf.patches cat >lockf.patches <<'@EOF' *** perl.3.0/arg.h Wed Nov 14 08:36:06 1990 --- perl.3.0.patch41.virgin/arg.h Wed Nov 14 08:28:42 1990 *************** *** 315,322 **** #define O_FTCTIME 265 #define O_WAITPID 266 #define O_ALARM 267 ! #define O_LOCKF 268 ! #define MAXO 269 #ifndef DOINIT extern char *opname[]; --- 315,321 ---- #define O_FTCTIME 265 #define O_WAITPID 266 #define O_ALARM 267 ! #define MAXO 268 #ifndef DOINIT extern char *opname[]; *************** *** 590,597 **** "FTCTIME", "WAITPID", "ALARM", ! "LOCKF", ! "269" }; #endif --- 589,595 ---- "FTCTIME", "WAITPID", "ALARM", ! "268" }; #endif *************** *** 990,996 **** A(1,0,0), /* FTCTIME */ A(1,1,0), /* WAITPID */ A(1,0,0), /* ALARM */ - A(1,1,1), /* LOCKF */ 0 }; #undef A --- 988,993 ---- *** perl.3.0/config_h.SH Wed Nov 14 10:27:19 1990 --- perl.3.0.patch41.virgin/config_h.SH Wed Nov 14 08:28:43 1990 *************** *** 160,171 **** */ #$d_flock FLOCK /**/ - /* LOCKF: - * This symbol, if defined, indicates that the lockf() routine is - * available to do file locking. - */ - #$d_lockf LOCKF /**/ - /* GETGROUPS: * This symbol, if defined, indicates that the getgroups() routine is * available to get the list of process groups. If unavailable, multiple --- 160,165 ---- *** perl.3.0/eval.c Wed Nov 14 08:52:42 1990 --- perl.3.0.patch41.virgin/eval.c Wed Nov 14 08:28:52 1990 *************** *** 1901,1930 **** str_set(str,"0 but true"); STABSET(str); break; - case O_LOCKF: - #ifdef LOCKF - if (maxarg <= 0) - stab = last_in_stab; - else if ((arg[1].arg_type & A_MASK) == A_WORD) - stab = arg[1].arg_ptr.arg_stab; - else - stab = stabent(str_get(st[1]),TRUE); - if (stab && stab_io(stab)) - fp = stab_io(stab)->ifp; - else - fp = Nullfp; - if (fp) { - argtype = (int)str_gnum(st[2]); - when = (long)str_gnum(st[3]); - value = (double)(lockf(fileno(fp),argtype,when) >= 0); - } - else - value = 0; - goto donumset; - #else - fatal("The lockf() function is unimplemented on this machine"); - break; - #endif case O_FLOCK: #ifdef FLOCK if (maxarg <= 0) --- 1901,1906 ---- *** perl.3.0/toke.c Wed Nov 14 08:38:11 1990 --- perl.3.0.patch41.virgin/toke.c Wed Nov 14 08:29:35 1990 *************** *** 953,960 **** FOP2(O_LISTEN); if (strEQ(d,"lstat")) FOP(O_LSTAT); - if (strEQ(d,"lockf")) - FOP3(O_LOCKF); break; case 'm': case 'M': if (s[1] == '\'') { --- 953,958 ---- *** perl.3.0/Configure Wed Nov 14 10:25:44 1990 --- perl.3.0.patch41.virgin/Configure Wed Nov 14 08:28:39 1990 *************** *** 114,120 **** d_fchown='' d_fcntl='' d_flock='' - d_lockf='' d_getgrps='' d_gethent='' d_getpgrp='' --- 114,119 ---- *************** *** 1708,1717 **** set flock d_flock eval $inlibc - : see if lockf exists - set lockf d_lockf - eval $inlibc - : see if getgroups exists set getgroups d_getgrps eval $inlibc --- 1707,1712 ---- *************** *** 2712,2718 **** d_fchown='$d_fchown' d_fcntl='$d_fcntl' d_flock='$d_flock' - d_lockf='$d_lockf' d_getgrps='$d_getgrps' d_gethent='$d_gethent' d_getpgrp='$d_getpgrp' --- 2707,2712 ---- *** perl.3.0/config_h.SH Wed Nov 14 10:27:19 1990 --- perl.3.0.patch41.virgin/config_h.SH Wed Nov 14 08:28:43 1990 *************** *** 160,171 **** */ #$d_flock FLOCK /**/ - /* LOCKF: - * This symbol, if defined, indicates that the lockf() routine is - * available to do file locking. - */ - #$d_lockf LOCKF /**/ - /* GETGROUPS: * This symbol, if defined, indicates that the getgroups() routine is * available to get the list of process groups. If unavailable, multiple --- 160,165 ---- *** perl.3.0/perl_man.2 Wed Nov 14 10:30:13 1990 --- perl.3.0.patch41.virgin/perl_man.2 Wed Nov 14 08:29:09 1990 *************** *** 650,660 **** Useful for constructing bitmaps for select(). If FILEHANDLE is an expression, the value is taken as the name of the filehandle. - .Ip "lockf(FILEHANDLE,FUNCTION,SIZE)" 8 4 - Calls lockf(2) on FILEHANDLE. - See manual page for lockf(2) for definition of OPERATION and SIZE. - Will produce a fatal error if used on a machine that doesn't implement - lockf(2). .Ip "flock(FILEHANDLE,OPERATION)" 8 4 Calls flock(2) on FILEHANDLE. See manual page for flock(2) for definition of OPERATION. --- 650,655 ---- @EOF chmod 666 lockf.patches echo x - op.lockf cat >op.lockf <<'@EOF' #!./perl # $Header$ sub lockftest { local($op, $size) = @_; local($got,*FOOBAR); if (fork() == 0) { open(FOOBAR,'op.lockf') || open(FOOBAR,'t/op.lockf') || exit -1; $got = lockf(FOOBAR, $op, $size); print "# child($$) got $got ($!)\n"; close(FOOBAR); exit $got; } wait; return($? >> 8); } print "1..8\n"; open(FOO,'op.lockf') || open(FOO,'t/op.lockf') || die "Can't open op.lockf"; # Lock it $got = lockf(FOO, 1, 0); print "# parent($$) got $got ($!)\n"; print ($got ? "ok 1\n" : "not ok 1\n"); # Test after fork $got = &lockftest(2, 0); print ((! $got) ? "ok 2\n" : "not ok 2\n"); # Unlock $got = lockf(FOO, 0, 0); print "# parent($$) got $got ($!)\n"; print ($got ? "ok 3\n" : "not ok 3\n"); # Now try test after fork $got = &lockftest(2, 0); print ($got ? "ok 4\n" : "not ok 4\n"); # Non overlapping locked regions $got = seek(FOO, 10, 0); if ($got) { $got = lockf(FOO, 1, 10); print "# parent($$) got $got ($!)\n"; print ($got ? "ok 5\n" : "not ok 5\n"); $got = &lockftest(2, 10); print ($got ? "ok 6\n" : "not ok 6\n"); lockf(FOO, 0, 10); } else { print "seek failed ($!)\n"; print "not ok 5\n"; print "not ok 6\n"; } # Overlapping locked regions $got = seek(FOO, 10, 0); if ($got) { $got = lockf(FOO, 1, 10); print "# parent($$) got $got ($!)\n"; print ($got ? "ok 7\n" : "not ok 7\n"); $got = &lockftest(2, 15); print ((! $got) ? "ok 8\n" : "not ok 8\n"); lockf(FOO, 0, 10); } else { print "seek failed ($!)\n"; print "not ok 7\n"; print "not ok 8\n"; } close(FOOBAR); @EOF chmod 755 op.lockf exit 0
tchrist@convex.COM (Tom Christiansen) (02/02/91)
I'm a bit nervous about using lockf() in all possible applicaltions. It requires (on Suns and Convexen at least) rpc.lockd to be running. flock() on the other hand is quick and can be run single user. --tom -- "Hey, did you hear Stallman has replaced /vmunix with /vmunix.el? Now he can finally have the whole O/S built-in to his editor like he always wanted!" --me (Tom Christiansen <tchrist@convex.com>)
thurlow@convex.com (Robert Thurlow) (02/02/91)
In <1991Feb1.074602.25583@robobar.co.uk> ronald@robobar.co.uk (Ronald S H Khoo) writes: >Hmm.. but wouldn't it make perl programs more portable if >you actually implemented the perl flock() function with lockf() ? >(Or don't the idioms match ? I haven't got a flock(2) manual page ....) I know of no BSD/Sun based machines which support any form of mapping between flock() and lockf(). An flock() style file lock does not in any way prevent someone from locking either a file region or an entire file with lockf(), or vice versa. Yes, this is stupid. Yes, the two locks can be mapped. But they've not been as far as I know. Anyone can jump in here to point out counterexamples with my thanks. What's the take on this in the System V universe? The last System V machine I worked on supported only lockf()/fcntl() style locking, with either advisory or enforcement locks as a kernel tunable. flock() is really a pretty limited idiom, so I never saw motivation to port it to SysV. The big reason it's so popular on BSD/Sun machines is that the Sun lock manager has traditionally been fraught with reliability problems. Rob T -- Rob Thurlow, thurlow@convex.com An employee and not a spokesman for Convex Computer Corp., Dallas, TX
ronald@robobar.co.uk (Ronald S H Khoo) (02/05/91)
tchrist@convex.COM (Tom Christiansen) writes: > I'm a bit nervous about using lockf() in all possible applicaltions. It > requires (on Suns and Convexen at least) rpc.lockd to be running. flock() > on the other hand is quick and can be run single user. Hmm.. Did I say use lockf() in all applications ? I musta been asleep :-) I probably meant to say "possibly include a flock() emulator written in terms of lockf() for sites without flock()" so that perl programs written with the *perl* flock() function have some chance of working on stock System V machines ? Is this reasonable? Does flock() map onto lockf() well enough for this approach to work ? -- Ronald Khoo <ronald@robobar.co.uk> +44 81 991 1142 (O) +44 71 229 7741 (H)
allbery@NCoast.ORG (Brandon S. Allbery KB8JRR) (02/09/91)
As quoted from <1991Feb4.214044.2422@robobar.co.uk> by ronald@robobar.co.uk (Ronald S H Khoo): +--------------- | I probably meant to say "possibly include a flock() emulator written in | terms of lockf() for sites without flock()" so that perl programs | written with the *perl* flock() function have some chance of working | on stock System V machines ? Is this reasonable? Does flock() map | onto lockf() well enough for this approach to work ? +--------------- Sure. Just lock from bytes 0 to the maximum system file size (*not* to the end of the file! That would still let any process append to the file). ++Brandon -- Me: Brandon S. Allbery VHF/UHF: KB8JRR on 220, 2m, 440 Internet: allbery@NCoast.ORG Packet: KB8JRR @ WA8BXN America OnLine: KB8JRR AMPR: KB8JRR.AmPR.ORG [44.70.4.88] uunet!usenet.ins.cwru.edu!ncoast!allbery Delphi: ALLBERY