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