Hi Edward,

Edward Lopez-Acosta wrote on Thu, Aug 09, 2018 at 06:29:04PM -0500:

> I was looking to port bleachbit, system cleanup tool, to OpenBSD
> and one function is to make sure certain files are not in use before
> it proceeds.

Strictly speaking, that is impossible due to a TOCTOU race condition.
You cannot do the check and the removal atomically in one step.
If you do the check and find that no process has it open, then by
the time you proceed to removing it, another process may have opened
it.  Or even worse, someone may have deleted the old file or moved
it to a different name and a third person may have created a
completely new file for a completely different purpose with the old
name.  None of that is OpenBSD-specific, by the way, the same
arguments hold on Linux.

If you are willing to ignore the dangers posed by such race conditions,
then both fuser(1) and fstat(1) can be used: both take "file"
arguments.

By the way, i just confirmed that the /proc/PID/fd/FDNUM filename
feature is indeed broken on Linux:

   $ uname -a
  Linux donnerwolke.asta-kit.de 4.9.0-0.bpo.3-686 #1 SMP Debian
  4.9.30-2+deb9u5~bpo8+1 (2017-09-28) i686 GNU/Linux
   $ cd /tmp
   $ touch old.txt
   $ tail -f old.txt

In another terminal:

   $ cd /tmp
   $ ln old.txt new.txt
   $ rm old.txt
   $ pgrep tail
  24052
   $ readlink /proc/24052/fd/3
  /tmp/old.txt (deleted)
   $ lsof | grep new.txt
   $ lsof | grep tail | grep 3r
  /tmp/old.txt (deleted)

So the kernel claims that "new.txt" is not open by any process,
and it also claims that the file open by tail(1) can no longer
be accessed via the file system.  However, typing

   $ echo test >> new.txt

in the second terminal makes "test" appear on the first terminal,
so it is a totally normal, fully functional file.

So the description

  "Obsolete package: lsof (ancient software that doesn't work)"

is indeed accurate.  If lsof says a file isn't open, it may well
be open anyway.  If lsof says a file was deleted, that may be an
outright lie.  If lsof reports that a given process has a file open
with some name, then that name may be neither the name the process
used for opening the file nor any of the names the file has now,
though it usually is one of the names that the file may have had
at some undefined time in between.  You cannot rely on any of those
statements from lsof because making such statements is just impossible
by the basic way how UNIX (including Linux) works, even without any
race conditions.  And then you get the race conditions on top of
all that.  Enjoy the mix!

Yours,
  Ingo

Reply via email to