Search code examples
unixexecsolaris-10fcntl

fcntl() with exec in Solaris


I use fcntl() for file capture and then I call execlp() to open file by nano. I run the program here and in another session. Process from new session also open the file by nano, but it should be waiting for unlock. Effect is same for mandatory and advisory lock.

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define editor "nano"

int main(int argc, char *argv[]) {
struct flock lock;
int fd;

if ((fd = open(argv[1], O_RDWR)) == -1) {
        perror("Cannot open file");
        exit(EXIT_FAILURE);
}
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;

if (fcntl(fd, F_SETLKW, &lock) == -1) {
        perror("fcntl failed");
        exit(EXIT_FAILURE);
}

execlp(editor, editor, argv[1], NULL);
perror("exec is not working");
exit(EXIT_FAILURE);
}

Man: The new process also inherits the following attributes from the calling process: ... file-locks (see fcntl(2) and lockf(3C))

How is it possible?


Solution

  • Per the Solaris 10 fcntl() man page:

    All locks associated with a file for a given process are removed when a file descriptor for that file is closed by that process

    Running the command truss -f -a -vall -l -d -o tout nano test.c produces the following lines in the truss output:

    Base time stamp:  1527722170.2660  [ Wed May 30 19:16:10 EDT 2018 ]
    6621/1:      0.0000 execve("/usr/bin/nano", 0xFEFFEADC, 0xFEFFEAE8)  argc = 2
    6621/1:      argv: nano test.c
    ...
    6621/1:      0.0417 open64("/home/achenle/junk/test.c", O_RDONLY)   = 3
    6621/1:      0.0418 fcntl(3, F_GETFD, 0xFEFFEA98)           = 0
    6621/1:      0.0422 fstat64(3, 0xFEFFE6A0)              = 0
    6621/1:         d=0x045D0009 i=418292 m=0100644 l=1  u=1000  g=100   sz=708
    6621/1:         at = May 30 19:09:05 EDT 2018  [ 1527721745.204432507 ]
    6621/1:         mt = May 30 19:04:25 EDT 2018  [ 1527721465.715445770 ]
    6621/1:         ct = May 30 19:04:25 EDT 2018  [ 1527721465.833365263 ]
    6621/1:         bsz=1024  blks=3     fs=lofs
    6621/1:      0.0424 fstat64(3, 0xFEFFE5B0)              = 0
    6621/1:         d=0x045D0009 i=418292 m=0100644 l=1  u=1000  g=100   sz=708
    6621/1:         at = May 30 19:09:05 EDT 2018  [ 1527721745.204432507 ]
    6621/1:         mt = May 30 19:04:25 EDT 2018  [ 1527721465.715445770 ]
    6621/1:         ct = May 30 19:04:25 EDT 2018  [ 1527721465.833365263 ]
    6621/1:         bsz=1024  blks=3     fs=lofs
    6621/1:      0.0425 ioctl(3, TCGETA, 0xFEFFE650)            Err#25 ENOTTY
    6621/1:      0.0426 read(3, " # i n c l u d e   < s y".., 1024) = 708
    6621/1:      0.0428 read(3, 0x0814D794, 1024)           = 0
    6621/1:      0.0428 llseek(3, 0, SEEK_CUR)              = 708
    6621/1:      0.0429 close(3)                    = 0
    

    That final close(3) releases all locks on the file. And note that it happens less than 5/100 of a second after nano starts.