Subject: init(8) keeps /var/run/utmpx locked ?
To: NetBSD current <current-users@NetBSD.org>
From: Nicolas Joly <njoly@pasteur.fr>
List: current-users
Date: 02/03/2007 15:51:14
--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


Hi,

While looking for a potential compat linux problem with uptime, i just
discovered that init(8) seems to keep /var/run/utmpx open and locked.

The linux uptime binary opens utmpx file, and then try to setup a
fcntl(2) F_SETLKW lock ... The problem is that this syscall is always
interrupted after 1 sec and thus fails (due to previous alarm
syscall).

njoly@cixy [~]> ktruss /emul/linux/usr/bin/uptime
[...]
   556      1 uptime   access("/emul/linux/var/run/utmpx", 0) = 0
   556      1 uptime   open("/emul/linux/var/run/utmpx", 0x2, 0xbbbe5010) Err#-13
   556      1 uptime   open("/emul/linux/var/run/utmpx", 0, 0xbbbe5010) = 3
   556      1 uptime   fcntl64(0x3, 0x1, 0)        = 0
   556      1 uptime   fcntl64(0x3, 0x2, 0x1)      = 0
   556      1 uptime   llseek(0x3, 0, 0, 0xbfbfc644, 0) = 0
   556      1 uptime   alarm(0)                    = 0
   556      1 uptime   rt_sigaction(0xe, 0xbfbfc468, 0xbfbfc3d8, 0x8) = 0
   556      1 uptime   alarm(0x1)                  = 0
   556      1 uptime   fcntl64(0x3, 0x7, 0xbfbfc660) Err#-4
   556      1 uptime   SIGALRM caught handler=0xbbbbaaf0 mask=0x0 code=0x0
   556      1 uptime   sigreturn(0xbfbfc484)       JUSTRETURN
   556      1 uptime   alarm(0)                    = 0
   556      1 uptime   rt_sigaction(0xe, 0xbfbfc468, 0, 0x8) = 0
   556      1 uptime   close(0x3)                  = 0
[...]

I then checked which processes were good candidates for holding a lock
on that file, and it looks like init(8) was the only one.

njoly@cixy [~]> lsof /var/run/utmpx
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
init      1 root    0u  VREG   0,13     7680 439304 /var/run/utmpx

Just to be sure, i recompiled init without umtpx support, and the
problem disappeared ...

   166      1 uptime   alarm(0x1)                  = 0
   166      1 uptime   fcntl64(0x3, 0x7, 0xbfbfc6d0) = 0
   166      1 uptime   read(0x3, 0xbbbe7700, 0x180) = 384
   166      1 uptime   fcntl64(0x3, 0x7, 0xbfbfc6d0) = 0
   166      1 uptime   alarm(0)                    = 1

In the mean time, i was able to reproduce the locking problem with the
attached small piece of code ... Just to be sure that compat linux has
no side effects.

  1860      1 fcntl    open("/var/run/utmpx", 0, 0) = 3
  1860      1 fcntl    setitimer(0, 0x7f7fffffea70, 0x7f7fffffea50) = 0
  1860      1 fcntl    fcntl(0x3, 0x9, 0x7f7fffffeae0) Err#4 EINTR
  1860      1 fcntl    SIGALRM caught handler=0x4009f0 mask=0x0 code=0x0
  1860      1 fcntl    setcontext(0x7f7fffffe700)  JUSTRETURN
  1860      1 fcntl    setitimer(0, 0x7f7fffffea70, 0x7f7fffffea50) = 0
  1860      1 fcntl    close(0x3)                  = 0

Thanks.

-- 
Nicolas Joly

Biological Software and Databanks.
Institut Pasteur, Paris.

--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fcntl.c"

#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

static void timeout_handler (int signum) {};

int main() {
  int fd;
  struct flock f;
  struct sigaction action, old_action;

  memset(&f, 0, sizeof(struct flock));
  f.l_type = F_RDLCK;
  f.l_whence = SEEK_SET;

  alarm(0);

  action.sa_handler = timeout_handler;
  sigemptyset (&action.sa_mask);
  action.sa_flags = 0;
  sigaction(SIGALRM, &action, &old_action);

  fd = open("/var/run/utmpx", O_RDONLY, 0);
  alarm(1);
  fcntl(fd, F_SETLKW, &f);
  alarm(0);
  close(fd);

  return 0; }

--TB36FDmn/VVEgNH/--