Skip site navigation (1)Skip section navigation (2)
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>