Date: Thu, 25 Feb 1999 12:27:15 -0800 (PST) From: jplevyak@inktomi.com To: freebsd-gnats-submit@freebsd.org Subject: kern/10265: file locking does not work with kernel pthreads Message-ID: <19990225202715.9F72F14F96@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 10265 >Category: kern >Synopsis: file locking does not work with kernel pthreads >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Feb 25 12:30:00 PST 1999 >Closed-Date: >Last-Modified: >Originator: John Plevyak >Release: 3.1-RELEASES >Organization: Inktomi >Environment: FreeBSD freebsd.inktomi.com 3.1-RELEASE FreeBSD 3.1-RELEASE #25: Thu Feb 25 11:53:01 GMT 1999 root@freebsd.inktomi.com:/usr/src/sys/compile/INKTOMI i386 >Description: releases of file locks depend on the close coming from the same PID as took out the lock. Since kernel threads have different PIDs it is possible for a peer thread to close the file locked by another peer. This results in the file lock not being cleared. >How-To-Repeat: compile with -D_THREAD_SAFE=1 -DLINUXTHREADS=1 -lpthread #include <fcntl.h> #include <signal.h> #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <pthread.h> pthread_t ink_thread_create(void*(*f)(void *),void * a) { pthread_t t; int ret; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); ret = pthread_create(&t, &attr, f, a); assert(!ret); pthread_attr_destroy(&attr); return t; } int lockfile_open (const char *lockfile, int *fd_ptr) { #define FAIL(x) \ { \ if (fd > 0) \ close (fd); \ return (x); \ } struct flock lock; int size; int val; int err; int fd; *fd_ptr = -1; // Try and open the lockfile. Create it if it does not already // exist. do { fd = open (lockfile, O_RDWR | O_CREAT, 0600); } while ((fd < 0) && (errno == EINTR)); if (fd < 0) FAIL (-errno); // Lock it. Note that if we can't get the lock EAGAIN will be the // error we receive. lock.l_type = F_WRLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; do { err = fcntl (fd, F_SETLK, &lock); } while ((err < 0) && (errno == EINTR)); if (err < 0) FAIL(0); // Return the file descriptor of the opened lockfile. When this file // descriptor is closed the lock will be released. *fd_ptr = fd; return(1); // success #undef FAIL } void * dthread(void * a) { (void)kill(0, SIGKILL); // or (void)kill(getpid(), SIGKILL); } int main(int argc, char ** argv) { int fd, i; int res = lockfile_open("lockfile.lock", &fd); printf("res = %d, fd = %d\n", res, fd); if (!res) exit(0); ink_thread_create(dthread, 0); sleep(10); } >Fix: Index: kern_descrip.c =================================================================== RCS file: /usr/cvsroot/src/sys/kern/kern_descrip.c,v retrieving revision 1.58 diff -c -r1.58 kern_descrip.c *** kern_descrip.c 1999/01/08 17:31:08 1.58 --- kern_descrip.c 1999/02/25 10:55:23 *************** *** 287,302 **** if ((fp->f_flag & FREAD) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; ! return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_WRLCK: if ((fp->f_flag & FWRITE) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; ! return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_UNLCK: ! return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, F_POSIX)); default: --- 287,302 ---- if ((fp->f_flag & FREAD) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; ! return (VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK, & fl, flg)); case F_WRLCK: if ((fp->f_flag & FWRITE) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; ! return (VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK, & fl, flg)); case F_UNLCK: ! return (VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK, & fl, F_POSIX)); default: *************** *** 317,323 **** return (EINVAL); if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; ! if ((error = VOP_ADVLOCK(vp,(caddr_t)p,F_GETLK,&fl,F_POSIX))) return (error); return (copyout((caddr_t)&fl, (caddr_t)(intptr_t)uap->arg, sizeof(fl))); --- 317,323 ---- return (EINVAL); if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; ! if ((error = VOP_ADVLOCK(vp,(caddr_t)p->p_leader,F_GETLK,&fl,F_P OSIX))) return (error); return (copyout((caddr_t)&fl, (caddr_t)(intptr_t)uap->arg, sizeof(fl))); *************** *** 1047,1053 **** lf.l_len = 0; lf.l_type = F_UNLCK; vp = (struct vnode *)fp->f_data; ! (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); } if (--fp->f_count > 0) return (0); --- 1047,1053 ---- lf.l_len = 0; lf.l_type = F_UNLCK; vp = (struct vnode *)fp->f_data; ! (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK, &lf, F_POS IX); } if (--fp->f_count > 0) return (0); Index: kern_exit.c =================================================================== RCS file: /usr/cvsroot/src/sys/kern/kern_exit.c,v retrieving revision 1.71.2.1 diff -c -r1.71.2.1 kern_exit.c *** kern_exit.c 1999/01/27 20:51:41 1.71.2.1 --- kern_exit.c 1999/02/25 11:52:30 *************** *** 141,162 **** kill(p, &killArgs); nq = q; q = q->p_peers; - /* - * orphan the threads so we don't mess up - * when they call exit - */ - nq->p_peers = 0; - nq->p_leader = nq; } - /* otherwise are we a peer? */ - } else if(p->p_peers) { - q = p->p_leader; - while(q->p_peers != p) - q = q->p_peers; - q->p_peers = p->p_peers; - } - #ifdef PGINPROF vmsizmon(); #endif --- 141,151 ---- kill(p, &killArgs); nq = q; q = q->p_peers; } + while (p->p_peers) + tsleep((caddr_t)p, PWAIT, "exit1", 0); + } #ifdef PGINPROF vmsizmon(); #endif *************** *** 197,202 **** --- 186,199 ---- * This may block! */ fdfree(p); + + if(p->p_leader->p_peers) { + q = p->p_leader; + while(q->p_peers != p) + q = q->p_peers; + q->p_peers = p->p_peers; + wakeup((caddr_t)p->p_leader); + } /* * XXX Shutdown SYSV semaphores >Release-Note: >Audit-Trail: >Unformatted: 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?19990225202715.9F72F14F96>