fcntl.flock - how to implement a timeout?
Question: I am using python 2.7

I want to create a wrapper function around fcntl.flock() that will timeout
after a set interval:

    
    
    wrapper_function(timeout):
    

I've tried calling on another thread and using thread.join(timeout) but it
seems that fcntl.flock() continues blocking:

    
    
    def GetLock(self, timeout):
        """Returns true if lock is aquired, false if lock is already in use"""
        self.__lock_file = open('proc_lock', 'w')
    
        def GetLockOrTimeOut():
            print 'ProcessLock: Acquiring Lock'            
            fcntl.flock(self.__lock_file.fileno(), fcntl.LOCK_EX)
            print 'ProcessLock: Lock Acquired'
    
        thread = threading.Thread(target=GetLockOrTimeOut)
        thread.start()
        thread.join(timeout)
    
        if thread.isAlive():
            print 'GetLock timed out'
            return False
        else:
            return True
    

I've looked into solutions for terminating threads, the most popular solution
seems to be sub-classing threading.thread and adding a feature to raise an
exception in the thread. However, I came across a
[link](http://sebulba.wikispaces.com/recipe+thread2) that says this method
will not work with native calls, which I am pretty sure fcntl.flock() is
calling a native function. Suggestions?

Context: I am using a file-lock to create a single instance application but I
don't want a second instance of the application to sit around and hang until
the first instance terminates.


Answer: Timeouts for system calls are done with signals. Most blocking system calls
return with EINTR when a signal happens, so you can use `alarm` to implement
timeouts.

Here's a context manager that works with most system calls, causing IOError to
be raised from a blocking system call if it takes too long.

    
    
    import signal, errno
    from contextlib import contextmanager
    import fcntl
    
    @contextmanager
    def timeout(seconds):
        def timeout_handler(signum, frame):
            pass
    
        original_handler = signal.signal(signal.SIGALRM, timeout_handler)
    
        try:
            signal.alarm(seconds)
            yield
        finally:
            signal.alarm(0)
            signal.signal(signal.SIGALRM, original_handler)
    
    with timeout(1):
        f = open("test.lck", "w")
        try:
            fcntl.flock(f.fileno(), fcntl.LOCK_EX)
        except IOError, e:
            if e.errno != errno.EINTR:
                raise e
            print "Lock timed out"
    

