translating "create Semaphore" to Linux

Diez B. Roggisch deets at nospam.web.de
Fri Aug 29 07:46:30 EDT 2008


GHUM wrote:

> hello,
> 
> in my application I am using
> 
> hSem = win32event.CreateSemaphore (None, 1,
> 1,"stringincludinginterfaceandport")
> rt=win32event.WaitForSingleObject (hSem, 0)
> if rt != win32event.WAIT_TIMEOUT:
>    really_do_start_my_app()
> else:
>    print "application allready running"
> 
> to make sure that only ONE instance of the application is running at a
> time. (as it implements a local webserver, that is necessary. Two
> webservers listening on one port is bad)
> 
> Now I am going to make this application run on Linux. How can I get
> similiar behaviour on Linux?
> 
> I know of the .pid files that get written by some server processes ...
> BUT they do not get cleaned up on unclean shutdown of the application.
> 
> is there some better method?
> 
> Or some module which wraps the details of .pid-files quite nicely?
> (like "trying to remove to check if other instance is still
> running...., failing properly on missing write privs etc.)

You might consider using a cooperative file locking for that. I do this as
follows:


#-------------------------------------------------------------------------------

class LockFileCreationException(Exception):
    pass


#-------------------------------------------------------------------------------

class LockObtainException(Exception):
    pass


#-------------------------------------------------------------------------------

class LockFile(object):

    def __init__(self, name, fail_on_lock=False, cleanup=True):
        self.name = name
        self.cleanup = cleanup
        try:
            self.fd = os.open(name, os.O_WRONLY | os.O_CREAT | os.O_APPEND)
        except OSError, e:
            if e[0] == 2:
                raise LockFileCreationException()
        self.file = os.fdopen(self.fd, "w")
        lock_flags = fcntl.LOCK_EX
        if fail_on_lock:
            lock_flags |= fcntl.LOCK_NB
        try:
            fcntl.flock(self.file, lock_flags)
        except IOError, e:
            if e[0] == 11:
                raise LockObtainException()
            raise


    def __enter__(self):
        return self.file


    def __exit__(self, unused_exc_type, unused_exc_val, unused_exc_tb):
        self.file.close()
        # we are told to cleanup after ourselves,
        # however it might be that another process
        # has done so - so we don't fail in that
        # case.
        if self.cleanup:
            try:
                os.remove(self.name)
            except OSError, e:
                if not e[0] == 2:
                    raise


You can use the LockFile as context, and either block until the lock is
released (which is most probably not what you want), or fail with
LockObtainException.

Diez



More information about the Python-list mailing list