Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
LOCKFILE_CREATE(3)	   Linux Programmer's Manual	    LOCKFILE_CREATE(3)

NAME
       lockfile_create,	lockfile_remove, lockfile_touch, lockfile_check	- man-
       age lockfiles

SYNOPSIS
       #include	<lockfile.h>

       cc [ flag ... ] file ...	-llockfile [ library ]

       int  lockfile_create(  const char *lockfile, int	retrycnt, int flags [,
       struct lockargs args ] );
       int lockfile_remove( const char *lockfile );
       int lockfile_touch( const char *lockfile	);
       int lockfile_check( const char *lockfile, int flags  );

DESCRIPTION
       Functions to handle lockfiles in	an NFS safe way.

   lockfile_create
       The lockfile_create function creates a lockfile in an NFS safe way.

       If flags	is set to L_PID	or L_PPID then lockfile_create will  not  only
       check  for  an existing lockfile, but it	will read the contents as well
       to see if it contains a process id in ASCII. If	so,  the  lockfile  is
       only  valid  if that process still exists.  Otherwise, a	lockfile older
       than 5 minutes is considered to be stale.

       When creating a lockfile, if L_PID is set in flags,  then  the  current
       process'	 PID will be written to	the lockfile. Sometimes	it can be use-
       ful to use the parent's PID instead (for	example, the dotlockfile  com-
       mand uses that).	In such	cases you can use the L_PPID flag instead.

   lockfile_touch
       If  the	lockfile is on a shared	filesystem, it might have been created
       by a process on a remote	host. So the L_PID or L_PPID method of	decid-
       ing  if a lockfile is still valid or stale is incorrect and must	not be
       used.  If you are holding a lock	longer than 5 minutes, a call to lock-
       file_create by another process will consider the	lock stale and	remove
       it.   To	prevent	this, call lockfile_touch to refresh the lockfile at a
       regular interval	(every minute or so).

   lockfile_check
       This function checks if a valid lockfile	 is  already  present  without
       trying to create	a new lockfile.

   lockfile_remove
       Removes the lockfile.

RETURN VALUES
       lockfile_create returns one of the following status codes:

	  #define L_SUCCESS   0	   /* Lockfile created			    */
	  #define L_TMPLOCK   2	   /* Error creating tmp lockfile	    */
	  #define L_TMPWRITE  3	   /* Can't write pid int tmp lockfile	    */
	  #define L_MAXTRYS   4	   /* Failed after max.	number of attempts  */
	  #define L_ERROR     5	   /* Unknown error; check errno	    */
	  #define L_ORPHANED  7	   /* Called with L_PPID but parent is gone */
	  #define L_RMSTALE   8	   /* Failed to	remove stale lockfile	    */

       lockfile_check returns 0	if a valid lockfile is present.	If no lockfile
       or no valid lockfile is present,	-1 is returned.

       lockfile_touch  and  lockfile_remove return 0 on	success. On failure -1
       is returned and errno is	set appropriately. It is not an	error to lock-
       file_remove() a non-existing lockfile.

ALGORITHM
       The algorithm that is used to create a lockfile in an atomic way,  even
       over NFS, is as follows:

       1      A	unique file is created.	In printf format, the name of the file
	      is .lk%05d%x%s. The first	argument (%05d)	is the current process
	      id. The second argument (%x) consists of the 4 minor bits	of the
	      value returned by	time(2). The last argument is the system host-
	      name.

       2      Then  the	lockfile is created using link(2). The return value of
	      link is ignored.

       3      Now the lockfile is stat()ed. If the stat	fails, we go  to  step
	      6.

       4      The stat value of	the lockfile is	compared with that of the tem-
	      porary  file. If they are	the same, we have the lock. The	tempo-
	      rary file	is deleted and a value of 0 (success) is  returned  to
	      the caller.

       5      A	 check is made to see if the existing lockfile is a valid one.
	      If it isn't valid, the stale lockfile is deleted.

       6      Before retrying, we sleep	for n seconds. n is initially  5  sec-
	      onds,  but  after	 every	retry 5	extra seconds is added up to a
	      maximum of 60 seconds (an	incremental backoff). Then  we	go  to
	      step 2 up	to retries times.

REMOTE FILE SYSTEMS AND	THE KERNEL ATTRIBUTE CACHE
       These functions do not lock a file - they generate a lockfile.  However
       in  a  lot of cases, such as Unix mailboxes, all	concerned programs ac-
       cessing the mailboxes agree on the fact that  the  presence  of	<file-
       name>.lock means	that <filename>	is locked.

       If  you	are  using lockfile_create to create a lock on a file that re-
       sides on	a remote server, and you already have that file	open, you need
       to flush	the NFS	attribute cache	after locking. This is needed to  pre-
       vent the	following scenario:

       o  open /var/mail/USERNAME
       o  attributes, such as size, inode, etc are now cached in the kernel!
       o  meanwhile, another remote system appends data	to /var/mail/USERNAME
       o  grab lock using lockfile_create()
       o  seek to end of file
       o  write	data

       Now  the	 end of	the file really	isn't the end of the file - the	kernel
       cached the attributes on	open, and st_size is not the end of  the  file
       anymore.	 So  after  locking  the  file,	you need to tell the kernel to
       flush the NFS file attribute cache.

       The only	portable way to	do this	is  the	 POSIX	fcntl()	 file  locking
       primitives - locking a file using fcntl() has the fortunate side-effect
       of invalidating the NFS file attribute cache of the kernel.

       lockfile_create()  cannot do this for you for two reasons. One, it just
       creates a lockfile- it doesn't know which file you are actually	trying
       to  lock! Two, even if it could deduce the file you're locking from the
       filename, by just opening and closing it, it would invalidate  any  ex-
       isting  POSIX  locks  the program might already have on that file (yes,
       POSIX locking semantics are insane!).

       So basically what you need to do	is something like this:

	 fd = open("/var/mail/USER");
	 .. program code ..

	 lockfile_create("/var/mail/USER.lock",	x, y);

	 /* Invalidate NFS attribute cache using POSIX locks */
	 if (lockf(fd, F_TLOCK,	0) == 0) lockf(fd, F_ULOCK, 0);

       You have	to be careful with this	if you're putting this in an  existing
       program	that  might already be using fcntl(), flock() or lockf() lock-
       ing- you	might invalidate existing locks.

       There is	also a non-portable way. A lot of NFS  operations  return  the
       updated attributes - and	the Linux kernel actually uses these to	update
       the attribute cache. One	of these operations is chmod(2).

       So stat()ing a file and then chmod()ing it to st.st_mode	will not actu-
       ally change the file, nor will it interfere with	any locks on the file,
       but  it will invalidate the attribute cache. The	equivalent to use from
       a shell script would be

	 chmod u=u /var/mail/USER

PERMISSIONS
       If you are on a system that has a mail spool  directory	that  is  only
       writable	 by a special group (usually "mail") you cannot	create a lock-
       file directly in	the mailspool directory	without	special	permissions.

       Lockfile_create and lockfile_remove  check  if  the  lockfile  ends  in
       $USERNAME.lock,	and if the directory the lockfile is writable by group
       "mail". If so, an external set group-id mail executable (dotlockfile(1)
       ) is spawned to do the actual locking / unlocking.

FILES
       /usr/lib/liblockfile.so.1

AUTHOR
       Miquel van Smoorenburg

SEE ALSO
       dotlockfile(1), maillock(3), touchlock (3), mailunlock(3)

Linux Manpage			27 Januari 2021		    LOCKFILE_CREATE(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=lockfile_create&sektion=3&manpath=FreeBSD+Ports+14.3.quarterly>

home | help