1#!/usr/bin/env python 2# Copyright (C) 2010 Gabor Rapcsanyi (rgabor@inf.u-szeged.hu), University of Szeged 3# 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY 16# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR 19# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 23# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27"""This class helps to lock files exclusively across processes.""" 28 29import logging 30import os 31import sys 32import time 33 34 35_log = logging.getLogger("webkitpy.common.system.file_lock") 36 37 38class FileLock(object): 39 40 def __init__(self, lock_file_path, max_wait_time_sec=20): 41 self._lock_file_path = lock_file_path 42 self._lock_file_descriptor = None 43 self._max_wait_time_sec = max_wait_time_sec 44 45 def _create_lock(self): 46 if sys.platform in ('darwin', 'linux2', 'cygwin'): 47 import fcntl 48 fcntl.flock(self._lock_file_descriptor, fcntl.LOCK_EX | fcntl.LOCK_NB) 49 elif sys.platform == 'win32': 50 import msvcrt 51 msvcrt.locking(self._lock_file_descriptor, msvcrt.LK_NBLCK, 32) 52 53 def _remove_lock(self): 54 if sys.platform in ('darwin', 'linux2', 'cygwin'): 55 import fcntl 56 fcntl.flock(self._lock_file_descriptor, fcntl.LOCK_UN) 57 elif sys.platform == 'win32': 58 import msvcrt 59 msvcrt.locking(self._lock_file_descriptor, msvcrt.LK_UNLCK, 32) 60 61 def acquire_lock(self): 62 self._lock_file_descriptor = os.open(self._lock_file_path, os.O_TRUNC | os.O_CREAT) 63 start_time = time.time() 64 while True: 65 try: 66 self._create_lock() 67 return True 68 except IOError: 69 if time.time() - start_time > self._max_wait_time_sec: 70 _log.debug("File locking failed: %s" % str(sys.exc_info())) 71 os.close(self._lock_file_descriptor) 72 self._lock_file_descriptor = None 73 return False 74 75 def release_lock(self): 76 try: 77 if self._lock_file_descriptor: 78 self._remove_lock() 79 os.close(self._lock_file_descriptor) 80 self._lock_file_descriptor = None 81 os.unlink(self._lock_file_path) 82 except (IOError, OSError): 83 _log.debug("Warning in release lock: %s" % str(sys.exc_info())) 84