Re: Bug with fcntl locks, pthread mutexes, and threads?

Manoj Kasichainula (manojk@raleigh.ibm.com)
Tue, 27 Apr 1999 19:41:09 -0400


On Tue, Apr 27, 1999 at 07:14:28PM -0400, Me at IBM wrote:
> To reproduce it, I use the attached C program.

bleh. OK, it wasn't included before. It is now...

--- cut here ---
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <signal.h>
#include <pthread.h>

static struct flock lock_it;
static struct flock unlock_it;
static int fcntl_fd=-1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static int this_pid;

/*
* Initialize mutex lock.
* Must be safe to call this on a restart.
*/
void
accept_mutex_init(void)
{

lock_it.l_whence = SEEK_SET; /* from current point */
lock_it.l_start = 0; /* -"- */
lock_it.l_len = 0; /* until end of file */
lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
lock_it.l_pid = 0; /* pid not actually interesting */
unlock_it.l_whence = SEEK_SET; /* from current point */
unlock_it.l_start = 0; /* -"- */
unlock_it.l_len = 0; /* until end of file */
unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */
unlock_it.l_pid = 0; /* pid not actually interesting */

printf("opening test-lock-thing in current directory\n");
fcntl_fd = open("test-lock-thing", O_CREAT | O_WRONLY | O_EXCL, 0644);
if (fcntl_fd == -1)
{
perror ("open");
fprintf (stderr, "Cannot open lock file: %s\n", "test-lock-thing");
exit (1);
}
unlink("test-lock-thing");
}

void accept_mutex_on(int i)
{
int ret;

printf("%d, %ld UNLOCKED->pthread_mutex_lock\n", this_pid, pthread_self());
if (pthread_mutex_lock(&mutex) != 0) {
puts("pthread_mutex_lock");
exit(1);
}
printf("%d, %ld pthread_mutex_lock->fcntl\n", this_pid, pthread_self());
while ((ret = fcntl(fcntl_fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR) {
printf("%d, %ld pthread_mutex_lock->fcntl\n", this_pid, pthread_self());
continue;
}

if (ret < 0) {
perror ("fcntl lock_it");
exit(1);
}
printf("%d, %ld fcntl->LOCKED\n", this_pid, pthread_self());
}

void accept_mutex_off(int i)
{
printf("%d, %ld LOCKED->fcntl\n", this_pid, pthread_self());
if (fcntl (fcntl_fd, F_SETLKW, &unlock_it) < 0)
{
perror ("fcntl unlock_it");
exit(1);
}
printf("%d, %ld fcntl->pthread_mutex_unlock\n", this_pid, pthread_self());
if (pthread_mutex_unlock(&mutex) != 0) {
puts("pthread_mutex_unlock");
}
printf("%d, %ld pthread_mutex_unlock->UNLOCKED\n", this_pid, pthread_self());
}

void *lockfunction(void *sifl)
{
while (1) {
accept_mutex_on (1);
sleep(100000);
accept_mutex_off (1);
}
return NULL;
}

int main (int argc, char **argv)
{
int i;
int num_child = 2;
int pid;
pthread_t thread;

accept_mutex_init ();

for (i = 0; i < num_child; ++i) {
pid = fork();
if (pid == 0) {
this_pid = getpid();
pthread_create(&thread, NULL, lockfunction, NULL);
lockfunction(NULL);
exit(0);
} else if (pid == -1) {
perror ("fork");
exit (1);
}
}

for (i = 0; i < num_child; ++i) {
if (wait(NULL) == -1) {
perror ("wait");
}
}
exit(0);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/