How to lock and unlock pid file with “fcntl()”

后端 未结 1 630
不知归路
不知归路 2021-01-19 16:18

I make a reseach on the net and even on the stackoverflow inorder to find an example of using fcntl() to lock and unlock pid file \"/var/run/myapp.pid\"

相关标签:
1条回答
  • 2021-01-19 17:14

    As you tagged Linux, verbatim form man lockf (emphasis by me):

    On Linux, lockf() is just an interface on top of fcntl(2) locking. Many other systems implement lockf() in this way, but note that POSIX.1-2001 leaves the relationship between lockf() and fcntl(2) locks unspecified. A portable application should probably avoid mixing calls to these interfaces.

    So looking up the current glibc sources (eglibc-2.11.3/io/lockf.c) a possible usage of fcntl() to implement locking looks like this:

    /* Copyright (C) 1994,1996,1997,1998,2000,2003 Free Software Foundation, Inc.
       This file is part of the GNU C Library.
    
       The GNU C Library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
       The GNU C Library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
       You should have received a copy of the GNU Lesser General Public
       License along with the GNU C Library; if not, write to the Free
       Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
       02111-1307 USA.  */
    
    #include <sys/types.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <string.h>
    
    /* lockf is a simplified interface to fcntl's locking facilities.  */
    
    int
    lockf (int fd, int cmd, off_t len)
    {
      struct flock fl;
    
      memset ((char *) &fl, '\0', sizeof (fl));
    
      /* lockf is always relative to the current file position.  */
      fl.l_whence = SEEK_CUR;
      fl.l_start = 0;
      fl.l_len = len;
    
      switch (cmd)
        {
        case F_TEST:
          /* Test the lock: return 0 if FD is unlocked or locked by this process;
             return -1, set errno to EACCES, if another process holds the lock.  */
          fl.l_type = F_RDLCK;
          if (__fcntl (fd, F_GETLK, &fl) < 0)
            return -1;
          if (fl.l_type == F_UNLCK || fl.l_pid == __getpid ())
            return 0;
          __set_errno (EACCES);
          return -1;
    
        case F_ULOCK:
          fl.l_type = F_UNLCK;
          cmd = F_SETLK;
          break;
        case F_LOCK:
          fl.l_type = F_WRLCK;
          cmd = F_SETLKW;
          break;
        case F_TLOCK:
          fl.l_type = F_WRLCK;
          cmd = F_SETLK;
          break;
    
        default:
          __set_errno (EINVAL);
          return -1;
        }
    
      /* lockf() is a cancellation point but so is fcntl() if F_SETLKW is
         used.  Therefore we don't have to care about cancellation here,
         the fcntl() function will take care of it.  */
      return __fcntl (fd, cmd, &fl);
    }
    

    A few mods are necessary to firstly make this compile:

    • replace __fcntl with fcntl
    • replace __set_errno(<errno-define>) with errno = <errno-define>

    .. and secondly to have it become async-signal-save:

    • replace the call to memset() with appropriate assigments to the struct fcntl variable.
    0 讨论(0)
提交回复
热议问题