Date: Fri, 30 Apr 1999 09:10:02 -0700 (PDT) From: David G Andersen <danderse@cs.utah.edu> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/10971: ypserv segfaults regularly (really: Race condition in the Berkeley db library). Message-ID: <199904301610.JAA64925@freefall.freebsd.org>
index | next in thread | raw e-mail
The following reply was made to PR bin/10971; it has been noted by GNATS.
From: David G Andersen <danderse@cs.utah.edu>
To: freebsd-gnats-submit@freebsd.org
Cc: danderse@cs.utah.edu
Subject: Re: bin/10971: ypserv segfaults regularly (really: Race condition in the Berkeley db library).
Date: Fri, 30 Apr 1999 10:02:43 -0600 (MDT)
As I mentioned in email to -hackers, this is the ugly,
don't-commit-because-it-changes-the-DB-semantics fix we use to
make ypserv work for us. To apply it, compile a *separate* libc with the
patched hash_page.c (that's lib/libc/db/hash/hash_page.c if you're keeping
track), and then patch your yp_dblookup.c so it opens the database
readwrite, so it can obtain an exclusive (read) lock on the database.
Recompile ypserv and link it statically against the separate libc, and
voila, life is good.
Alternately, change hash_page.c (and the equivalent functions in the other
DB routines) to use pread with an absolute offset, instead of doing the
lseek()/read() race condition combo. This only works for people in
-current, but it's a better and faster fix.
-Dave
*** yp_dblookup.c 1998/02/11 19:15:32 1.15
--- yp_dblookup.c 1999/04/13 23:51:44
***************
*** 414,420 ****
#ifdef DB_CACHE
again:
#endif
! dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL);
if (dbp == NULL) {
switch(errno) {
--- 414,420 ----
#ifdef DB_CACHE
again:
#endif
! dbp = dbopen(buf, O_RDWR, PERM_SECURE, DB_HASH, NULL);
if (dbp == NULL) {
switch(errno) {
*** hash_page.c Fri Apr 2 15:36:00 1999
--- hash_page.c.locking Thu Apr 1 22:01:49 1999
***************
*** 524,529 ****
--- 524,530 ----
register int fd, page, size;
int rsize;
u_int16_t *bp;
+ struct flock fl;
fd = hashp->fp;
size = hashp->BSIZE;
***************
*** 536,544 ****
--- 537,556 ----
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
+
+ fl.l_start = fl.l_len = fl.l_pid = 0;
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+
+ fcntl(fd, F_SETLKW, &fl);
+
if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
((rsize = read(fd, p, size)) == -1))
return (-1);
+
+ fl.l_type = F_UNLCK;
+ fcntl(fd, F_SETLK, &fl);
+
bp = (u_int16_t *)p;
if (!rsize)
bp[0] = 0; /* We hit the EOF, so initialize a new
page */
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199904301610.JAA64925>
