[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

glibc 2.1 contained BSD DB 2.1 seems to leak mmap()s




To ZMailer users with similar machine (glibc 2.1) as mine this is a note
to pick a pseudo-cure from ZMailer CVS (http://www.zmailer.org/anoncvs.html);
that cure lowers the number of DB re-open instances, and thus lowers (a lot)
the rate of mmap() region leakage, and resulting harms.. Alternate "cure" is
to restart the routers every 5-10 minutes, but that is mad..

To GLIBC maintainers this is a question about a possible bug in the
included SleepyCat BSD DB 2.* database library.


This is a RedHat installation, so:
     # rpm -qf /lib/libdb.so.2.1
     glibc-2.1.1-7



The lattest ZMailer versions use the BSD DB 2.* which is coming with
the glibc 2.1, the DB open does mostly like this fragment shows:

  int err;
  DB * db = NULL;

  unlink("/tmp/ -mark1 -"); /* strace output marker */

  err = db_open(filename, DB_BTREE,
		DB_NOMMAP|((flag == O_RDONLY) ? DB_RDONLY:DB_CREATE),
		0644, NULL, NULL, &db);

  unlink("/tmp/ -mark2 -"); /* strace output marker */

(usually those strace markers are not in there, though)

At my Linux/Alpha system (at least) this seems to do some internal
tempfile open + mmap() of file:


7169  unlink("/tmp/ -mark1- ")          = -1 ENOENT (No such file or directory)
7169  open("/opt/mail/db/aliases.db", O_RDONLY) = 6
7169  fcntl(6, F_SETFD, FD_CLOEXEC)     = 0
7169  fstat(6, {...})                   = 0
7169  read(6, "\0\0\0\0\0\0\0\0\0\0\0\0b1\5\0\6\0\0\0\0 \0\0\0\0\0\0\2"..., 512) = 512
7169  close(6)                          = 0
7169  stat("/var/tmp", {...})           = 0
7169  stat("/var/tmp", {...})           = 0
7169  getxpid()                         = 7169
7169  open("/var/tmp/007169", O_RDWR|O_CREAT|O_EXCL, 0600) = 6
7169  fcntl(6, F_SETFD, FD_CLOEXEC)     = 0
7169  lseek(6, 0, SEEK_END)             = 0
7169  lseek(6, 98304, SEEK_CUR)         = 98304
7169  write(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
7169  mmap(NULL, 4831749088, 0x1000, 0x8 /* MAP_??? */, 0, 0) = 0x20000058000
7169  getxpid()                         = 7169
7169  fcntl(6, F_SETLKW, {...})         = 0
7169  fcntl(6, F_SETLK, {...})          = 0
7169  close(6)                          = 0
7169  unlink("/var/tmp/007169")         = 0
7169  open("/opt/mail/db/aliases.db", O_RDONLY) = 6
7169  fcntl(6, F_SETFD, FD_CLOEXEC)     = 0
7169  fstat(6, {...})                   = 0
7169  mmap(NULL, 4831753008, PROT_READ, 0x8 /* MAP_??? */, 0, 0) = 0x20000020000
7169  unlink("/tmp/ -mark2- ")          = -1 ENOENT (No such file or directory)


(the strace 3.99.1 is yielding crazy data for mmap(), but at least it
 doesn't crash like its predecessors.. but that is beside the point.)

So, within this sequence the tempfile is created, mmap()ed that 4k
block in (in system which page-size is 8k), and then the file is
unlinked.

Now if the database is decided to reopen for some reason (it has been
regenerated, or like ZMailer has done for ages: failed lookup is retried
with reopened db just in case it changed from underneath without other
tests noticing it; the second time failure is true..), then that mmap()ed
region is *not* freed by the   (db->close)(db,0);  call, and that invisible
4k block is leaking 1) in disk, and 2) in kernel as an open file.

Is this a known SleepyCat BSD DB 2.* problem, or not ?

/Matti Aarnio <mea@nic.funet.fi>