Search code examples
cmultithreadingfile-lockingflock

What is the scope of flock()?


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.


Solution

  • 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)