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>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199904301610.JAA64925>