user1267671
user1267671

Reputation: 68

Find PID of a process that locked a file

I need to find who locked a file using python (posix/linux). Currently I use this method:

flk = struct.pack('hhqql', fcntl.F_WRLCK, 0, 0, 0, 0)
flk = struct.unpack('hhqql', fcntl.fcntl(self.__file, fcntl.F_GETLK , flk))

if flk[0] == fcntl.F_UNLCK:
    # file is unlocked ...
else:
    pid = flk[4]

This solution is not architecture-independent. Structure passed to fcntl contains fields such as off_t or pid_t. I cannot make assumptions about sizes of those types.

struct flock {
    ...
    short l_type;    /* Type of lock: F_RDLCK,
                    F_WRLCK, F_UNLCK */
    short l_whence;  /* How to interpret l_start:
                    SEEK_SET, SEEK_CUR, SEEK_END */
    off_t l_start;   /* Starting offset for lock */
    off_t l_len;     /* Number of bytes to lock */
    pid_t l_pid;     /* PID of process blocking our lock
                    (F_GETLK only) */
    ...
};

Is there any other way to find the PID? Or maybe sizes of off_t and pid_t? The solution must be fully portable between different architectures.

Edit I decided to use lsof program as suggested below. Another option is to parse /proc/locks file.

Upvotes: 3

Views: 2057

Answers (2)

clayg
clayg

Reputation: 347

I had previously used 'hhllh' because I thought it would most closely map to off_t across platforms. But eventually I settled on 'hhqqh', which works for me on 32bit and 64bit systems.

I was surprised by this solution, but what seems to be going on for the the 32bit boxes I was looking at is bits/fcntl.h creates the flock struct with off64_t unless the system already defines __USE_FILE_OFFSET64 (in which case it just uses the regular 'ol off_t) so it seems like the size of l_start and l_len is always 8 (the python struct format char 'q' is long long).

This is probably not entirely portable, I can't say all modern 32bit systems are going to do this, but it was good enough for me for now - so I thought I'd mention it in case others (like myself) would rather not have to exec another process and do a bunch of string parsing, YMMV. Also if I'm misunderstanding (or poorly explaining) why this format string seems to work on both platforms - maybe someone could correct me?

Upvotes: 0

Adam
Adam

Reputation: 2361

Maybe you can try use external program, lsof, to do that?

   Lsof revision 4.85 lists on its standard output file information 
   about files opened by processes for the following UNIX dialects:

        AIX 5.3
        Apple Darwin 9 and Mac OS X 10.[56]
        FreeBSD 4.9 and 6.4 for x86-based systems
        FreeBSD 8.[02] and 9.0 for AMD64-based systems
        Linux 2.1.72 and above for x86-based systems
        Solaris 9, 10 and 11

Upvotes: 4

Related Questions