3

I'm testing if locking a file descriptor from an other thread will affect the main thread.

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
//#include <share.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>

void *print_message_function( void *ptr );

pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

int main (int argc, char * const argv[]) {

    pthread_t thread1, thread2;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
int  iret1, iret2;

    iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message1);

    if(iret2)
    {
        fprintf(stderr,"Error - pthread_create() return code: %d\n",iret2);
        fflush(stdout);
        exit(EXIT_FAILURE);
    }

        printf("pthread_create() for thread 2 returns: %d\n",iret2);

    pthread_mutex_lock(&mut);
    sleep(1);

    std::cout<<"Enter any key:"<<std::endl;
    std::cin >> input;

    if (fd2 = open( "file1",    O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10) == -1)
    {
        perror("Cannot open file 2.\n"); 
        fflush(stdout);
    }
    else
    {
        printf("File was opened 2!!\n");
        fflush(stdout);
        if(flock(fd2, LOCK_NB | LOCK_EX)==0)
        {
            printf("THE FILE WAS LOCKED 2.\n");
        }
        else if(errno == EAGAIN)
        {
            printf("The file is locked 2. Resource temporarily unavailable.\n");
        }
    }

    pthread_mutex_unlock(&mut);

    close(fd2);
    std::cout<<"File closed."<<std::endl;
    std::cin >> input;
    return 0;
}


void *print_message_function( void *ptr )
{
    char *message;
    message = (char *) ptr;
    printf("%s \n", message); 
    fflush(stdout);

    int fd1;

    if ((fd1 = open( "file1",   O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10)) == -1)
    {
        perror("thread: Cannot open file 1.\n");
        fflush(stdout);
        //std::cin >> input;
    }
    else
    {
        printf("File was opened 1!!\n");
        fflush(stdout);


        if(flock(fd1, LOCK_NB | LOCK_EX)==0)
        {
            printf("THE FILE WAS LOCKED 1.\n");
        }
        else if(errno == EAGAIN)
        {
            printf("The file is locked 1. Resource temporarily unavailable.\n");
        }
    }

    pthread_mutex_lock(&mut);
    pthread_mutex_unlock(&mut);

    printf("End of thread.\n");
}

The output:

[Session started at 2014-11-26 17:46:16 +0000.]
pthread_create() for thread 2 returns: 0
Thread 1 
File was opened 1!!
THE FILE WAS LOCKED 1.
Enter any key:
1
File was opened 2!!
THE FILE WAS LOCKED 2.
File closed.
End of thread.

I don't understand why flock() used inside the thread doesn't prevent flock() used in the main thread getting the lock.

From linux man page:

Locks created by flock() are associated with an open file description (see open(2)). This means that duplicate file descriptors (created by, for example, fork(2) or dup(2)) refer to the same lock, and this lock may be modified or released using any of these descriptors. Furthermore, the lock is released either by an explicit LOCK_UN operation on any of these duplicate descriptors, or when all such descriptors have been closed.

Sanich
  • 1,739
  • 6
  • 25
  • 43
  • possible duplicate of [multiple threads able to get flock at the same time](http://stackoverflow.com/questions/9462532/multiple-threads-able-to-get-flock-at-the-same-time) – pilcrow Nov 26 '14 at 17:15
  • @pilcrow, not a dupe. In the question you referenced, the various threads are using the same file descriptor (or if not, then none of the answers is satisfactory). In this case, they are opening separate descriptors on the same file. Per the docs, `flock()`s on distinct descriptors open on the same file may indeed block each other. – John Bollinger Nov 26 '14 at 19:06
  • 1
    It's a little odd that `print_message_function()` locks and unlocks the mutex at the end, but doesn't do any of its work within the scope of the mutex. Is the behavior different if you perform at least the `flock()` while holding the mutex (as the other thread already does)? Note: you'll want to move the main thread's `sleep()` out of its critical section. – John Bollinger Nov 26 '14 at 19:13

1 Answers1

5

Typo. This line incorrectly sets fd2 (which you did not declare in your posted code, by the way) to 0, viz., stdin:

if (fd2 = open( "file1",    O_RDWR | O_CREAT | O_TRUNC, 0700 | 0x10) == -1)

Thus, fd1 and fd2 almost certainly refer to different files and the point of your exercise is lost. You mean to say:

if ((fd2 = open("file1", ...)) == -1)
pilcrow
  • 56,591
  • 13
  • 94
  • 135