Is there a faster way to check if a file is in use?

I'm looking for a command line function or c function that will let me know if a file is open/in use by something.

lsof and fuser do tell this, but they provide a lot of other info which results in taking up to 300ms in some situations (like when i use this code on MAC OS X, I'm devving for Linux and OS X) (I have a windows solution that takes 5ms so I'm trying to find something in Unix that also is very quick, and just returns true or false if file is in use)


Solution 1:

If you are using this as a lock, it will not work as neither lsof or fuser prevent race conditions.

The basic process that lsof does is trawl through all processes /proc/*/fs looking for open file descriptors. This is going to take time no matter what you do.

You can do this yourself, but it is not likely to be any faster as you have to check for every open process on the system.

If what you are doing is time critical, figure out another way to do it.

  • If you control the file through a program that you wrote; use a lock file.
  • If you are running some command that operates on the file, look and see what documentation that command/program offers and see if it can't make a lockfile. Failing that, see if it can't make a file with its PID inside it. Then you can look at /proc/<PID>/fs to see if your file is currently open or not. Looking at only one processes open file descriptors will be much faster then mapping across all of them.
  • Otherwise in order to help you I am going to need more information about what you are doing.

You gave more information in a comment that you want to determine if Firefox is running on a given system. The best way to do this is to look for Firefox's lock files. These are stored in default locations specified on the Mozilla wiki.

For example, on linux, have your program do the following:

  • open up the ~/.mozilla/firefox/ directory.
  • List all directories, filtering for directories ending in .default. (I think all profiles end with .default, if not just crawl into every directory.)
  • In each directory above, look for the existence of a file named lock or .parentlock. If you see one or both files, Firefox is open.

This algorithm ought to execute faster than what you do on windows currently.

Solution 2:

TL;DR

In one of your comments, you state:

Well my exact situation is: I have the path to a file. It is locked if firefox is running. I want to see if its locked or not to tell if firefox is running.

Your original question about lockfiles seems like the long way around when there are easier ways to find out whether Firefox is running for a given user, and to inspect its process state.

Examining Process State

A more sensible way to find the PID of a given process is to use pgrep from the procps package. For example:

$ pgrep -u $LOGNAME firefox
5671

You can then inspect the state of the PID with ps:

$ ps 5671
  PID TTY      STAT   TIME COMMAND
 5671 ?        Sl   105:47 /usr/lib/firefox/firefox

or just get the state flags without any other cruft:

$ ps -ho stat $(pgrep -u $LOGNAME firefox)
Sl

One my system, the one-liner above consistently takes only 1.4 milliseconds to complete. Your mileage may vary.

Process State Codes

The PROCESS STATE CODES section of ps(1) details what the various state flags mean. On Ubuntu 14.04 the man page says:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output
       specifiers (header "STAT" or "S") will display to describe the state of
       a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is
                    being traced
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by
                    its parent

       For BSD formats and when the stat keyword is used, additional
       characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads
                    do)
               +    is in the foreground process group