11

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)

αғsнιη
  • 35,660
Noitidart
  • 417
  • 1
    http://superuser.com/questions/97844/how-can-i-determine-what-process-has-a-file-open-in-linux – Panther Sep 23 '14 at 18:54

2 Answers2

11

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.

nixeagle
  • 226
  • Excellent answer thank you. Is there anyway to tell lsof and fuser to only check the pid folder if it is firefox? That would make it skip all the contents of folders except for folders of firefox (I have 3 seperate instances so that means it just checks 3 folders right?) – Noitidart Sep 23 '14 at 19:40
  • The file is locked, but I can't figure out how to test if its locked. It is succesfully getting opened for read/write. Its so weird. I tried fcntl from c but its always returning -1 :( – Noitidart Sep 23 '14 at 19:40
  • 3
    @Noitidart What is your actual problem you are trying to solve? In order to lookup any process's open file descriptors you have to know its PID. This changes for each instance of the program. A simple way to get it "manually" is with ps aux firefox. Take those PIDs and look them up in the /proc/ filesystem. – nixeagle Sep 23 '14 at 19:46
  • ah thanks thats a good idea about ps aux firefox. 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. – Noitidart Sep 23 '14 at 19:47
  • @Noitidart if that is the case, you can simply use ps to look up what you need in order to tell if firefox is running. If you run ps aux | grep firefox you can use that information to tell if a process claiming to be firefox is running. Try it out and see if that is enough to solve your problem. If not, you might need to edit your question with more information about what you are doing. Are you trying to figure this out using a program? Script? What is the purpose of the program? The more information you give me, the quicker and more accurate my advice will be. – nixeagle Sep 23 '14 at 19:54
  • 1
    @Noitidart I have edited my comment to include how to detect firefox by looking at lock files. You can repeat this process on all systems. – nixeagle Sep 23 '14 at 20:09
  • That is such a great idea. I actually tried that, but even after you close firefox the .parentlock file continues to exist. I can't work with the lock file for special reasons. I actually have the full path to the .parentlock file of the profile i want to test (i get this information form the profiles.ini file in firefox directory) – Noitidart Sep 23 '14 at 20:12
1

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
CodeGnome
  • 240
  • 1
  • 10
  • 1
    the problem is that he needs to know which session firefox is currently in. On linux, you simply look for ~/.mozilla/firefox/*/lock. You can then identify the session by looking at the parent directory name of each lock file. On other platforms this does not work. Our chat goes more into how to get it working on macs (which is kinda irrelevant for ubuntu, but there you have it). To be fair, he really should update the question to be more specific. :P – nixeagle Sep 24 '14 at 14:46