Thread: Mutual Exclusion and Running a Single Copy [open,lockf,getpid]

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    61

    Mutual Exclusion and Running a Single Copy [open,lockf,getpid]

    Hi,
    I'm writing a daemon and now that must be run in a single process (two instance of process should not be executed at the same time). I tried this code, but it didn't work:
    Code:
        int lfp=open(LOCK_FILE, O_RDWR|O_CREAT,0640);
        if (lfp<0)
            cout << "Could not open lockfile" << endl;
    
        if ( lockf(lfp,F_TLOCK,0)<0 )
            exit(0); /* can not lock */
        
        /* first instance continues */
    
        char str[10];
        sprintf(str,"%d\n",getpid());
        write(lfp,str,strlen(str)); /* record pid to lockfile */
        close(lfp);
    What's wrong?!

    Thanks

  2. #2
    Registered User valaris's Avatar
    Join Date
    Jun 2008
    Location
    RING 0
    Posts
    507
    What are the errors/problems?

  3. #3
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    There is no compile error, but two or more instance of the program can still be executed at the same time (simultaneously)

  4. #4
    Registered User
    Join Date
    Nov 2008
    Posts
    75
    Try using the library "unique", instead of reinventing the wheel.

  5. #5
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    "unique" library?! What do you mean?! It's a C library or ... ?!

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    75

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Well, that's Gnome specific (with X11 dependencies). Internally it uses either Unix domain sockets or D-Bus.

    >> What's wrong?!
    Only thing I see wrong is that "if (lfp<0)" allows execution to continue.

    gg

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    A more reliable way is to use a UNIX socket. Two processes cannot both bind to the same UNIX socket name. As part of your startup, open and bind a UNIX socket at some known location (probably somewhere in /var). If you fail to bind, you know another instance is already running.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User
    Join Date
    Nov 2008
    Posts
    75
    Quote Originally Posted by Codeplug View Post
    Well, that's Gnome specific (with X11 dependencies). Internally it uses either Unix domain sockets or D-Bus.

    >> What's wrong?!
    Only thing I see wrong is that "if (lfp<0)" allows execution to continue.

    gg
    It's not gnome specific. It has dependencies(as can be seen from the link), but that's different from being gnome specific.

  10. #10
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    I would say it's "as realiable", since advisory-locks held by a process are removed when the descriptor is closed - and all descriptors are closed when the process exits. But sockets provide a comm. channel which may be useful.

    Which brings up the question: Are you sure that both processes are just acquiring and releasing the lock, one after another? If the code you posted is the code you're running, then that's probably the case.

    Also, you may want to ftruncate() the file once you acquire the lock to prevent any "left-overs" from previous write() of longer pids.

    >> It's not gnome specific.
    Sorry, GTK+, X11 dependent would be more accurate.

    gg

  11. #11
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    channel which may be useful.
    What's this?!

    Which brings up the question: Are you sure that both processes are just acquiring and releasing the lock, one after another? If the code you posted is the code you're running, then that's probably the case.
    With the code I posted, two execution of the program can be executed and the lockf return 0 for each of them!!!

  12. #12
    Registered User
    Join Date
    Jul 2009
    Posts
    61
    Hi,
    I used flock and it is working now
    flock(2) - Linux man page
    Code:
        int fd=open(LOCK_FILE, O_RDWR|O_CREAT,0640);
        if (fd<0)
            cout << "Could not open lockfile" << endl;
    
        int x=flock(fd,LOCK_EX | LOCK_NB);
        if( x<0 )
            exit(1);
        /* first instance continues */

Popular pages Recent additions subscribe to a feed