Show
Ignore:
Timestamp:
09/04/06 01:46:33 (18 years ago)
Author:
jerome
Message:

Rewrote the locking mechanism.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r2997 r3008  
    8787        self.pid = os.getpid() 
    8888        self.DataFile = None 
     89        self.lockfilename = None 
     90        self.lockfile = None 
    8991         
    9092    def deferredInit(self) :     
     
    128130        """Waits until we can acquire the lock file.""" 
    129131        self.logdebug("Waiting for lock...") 
    130         stillrunning = True 
     132        haslock = False 
    131133        try : 
    132             while 1 : 
    133                 self.lockfile = open(self.lockfilename, "a+") 
    134                 fcntl.lockf(self.lockfile, fcntl.LOCK_EX) # Will wait until lock available 
    135                 self.lockfile.seek(0, 0)       
    136                 try :  
    137                     oldpid = int(self.lockfile.readlines()[-1].strip()) 
    138                 except :     
    139                     stillrunning = False 
     134            while not haslock : 
     135                self.logdebug("Trying to acquire lock %s" % self.lockfilename) 
     136                try : 
     137                    self.lockfile = os.open(self.lockfilename,  
     138                                            os.O_CREAT | os.O_EXCL | os.O_WRONLY,  
     139                                            0600) 
     140                except OSError, error :                      
     141                    if error.errno == errno.EEXIST : 
     142                        self.logdebug("Lock not available.") 
     143                    else :     
     144                        self.logdebug("Lock not available : %s" % error) 
     145                    try :     
     146                        try :     
     147                            lockfobj = open(self.lockfilename, "r")     
     148                            oldpid = int(lockfobj.readline().strip()) 
     149                        except IOError : 
     150                            self.logdebug("Lock file has probably been deleted in the meantime.") 
     151                        except ValueError :     
     152                            self.logdebug("Invalid content in existing lock file.") 
     153                        else :     
     154                            try : 
     155                                # Is the old process still alive ? 
     156                                os.kill(oldpid, 0) 
     157                            except OSError :     
     158                                # old process is dead, we delete the lock file 
     159                                self.logdebug("Old process (PID %i) is dead." % oldpid) 
     160                                os.unlink(self.lockfilename) 
     161                                self.logdebug("Lock file %s removed." % self.lockfilename) 
     162                            else :     
     163                                self.logdebug("Old process (PID %i) still alive, waiting a bit..." % oldpid) 
     164                                time.sleep(0.25) # No hurry :) 
     165                    finally :     
     166                        try : 
     167                            lockfobj.close() 
     168                        except NameError :     
     169                            pass 
    140170                else :     
    141                     try : 
    142                         os.kill(oldpid, 0) 
    143                     except OSError :     
    144                         stillrunning = False 
    145                 if not stillrunning :         
    146                     self.lockfile.truncate(0) 
    147                     self.lockfile.seek(0, 0) 
    148                     self.lockfile.write("%s\n" % self.pid) 
    149                     self.lockfile.flush() 
    150                     break 
    151                 else :     
    152                     self.lockfile.close() 
    153                     time.sleep(0.1) 
     171                    os.write(self.lockfile, str(self.pid)) 
     172                    haslock = True     
    154173        except IOError :             
    155174            self.logdebug("I/O Error while waiting for lock.") 
     
    510529        self.regainPriv() 
    511530        self.deinstallSigTermHandler() 
    512         if not self.config.getPrinterKeepFiles(self.PrinterName) : 
    513             self.logdebug("Work file %s will be deleted." % self.DataFile) 
     531        if (self.DataFile is not None) and os.path.exists(self.DataFile) : 
     532            if not self.config.getPrinterKeepFiles(self.PrinterName) : 
     533                self.logdebug("Work file %s will be deleted." % self.DataFile) 
     534                try : 
     535                    os.remove(self.DataFile) 
     536                except OSError, msg : 
     537                    self.logdebug("Problem while deleting work file %s : %s" % (self.DataFile, msg)) 
     538                else : 
     539                    self.logdebug("Work file %s has been deleted." % self.DataFile) 
     540            else :     
     541                self.logdebug("Work file %s will be kept." % self.DataFile) 
     542        PyKotaTool.clean(self)     
     543        if (self.lockfile is not None) and os.path.exists(self.lockfilename) : 
     544            self.logdebug("Removing lock...") 
    514545            try : 
    515                 if os.path.exists(self.DataFile) : 
    516                     os.remove(self.DataFile) 
    517             except OSError, msg : 
    518                 self.logdebug("Problem while deleting work file %s : %s" % (self.DataFile, msg)) 
    519             else : 
    520                 self.logdebug("Work file %s has been deleted." % self.DataFile) 
    521         else :     
    522             self.logdebug("Work file %s will be kept." % self.DataFile) 
    523         PyKotaTool.clean(self)     
    524         self.logdebug("Removing lock...") 
    525         try : 
    526             fcntl.flock(self.lockfile, fcntl.LOCK_UN) 
    527             self.lockfile.close() 
    528             # NB : we don't remove the lock file, since it might already be opened by another process. 
    529         except :     
    530             pass 
    531         else :     
    532             self.logdebug("Lock removed.") 
     546                os.close(self.lockfile) 
     547                os.unlink(self.lockfilename) 
     548            except :     
     549                self.logdebug("Problem while removing lock file %s" % self.lockfilename) 
     550            else :     
     551                self.logdebug("Lock file %s removed." % self.lockfilename) 
    533552        self.logdebug("Clean.") 
    534553             
     
    13871406    else :     
    13881407        try : 
    1389             wrapper.deferredInit() 
    1390             wrapper.initBackendParameters() 
    1391             wrapper.waitForLock() 
    1392             if os.environ.get("PYKOTASTATUS") == "CANCELLED" : 
    1393                 raise KeyboardInterrupt 
    1394             wrapper.saveDatasAndCheckSum() 
    1395             wrapper.preaccounter = openAccounter(wrapper, ispreaccounter=1) 
    1396             wrapper.accounter = openAccounter(wrapper) 
    1397             wrapper.precomputeJobSize() 
    1398             wrapper.exportJobInfo() # exports a first time to give hints to external scripts  
    1399             wrapper.overwriteJobAttributes() 
    1400             wrapper.exportJobInfo() # re-exports in case it was overwritten 
    1401             retcode = wrapper.mainWork() 
    1402         except KeyboardInterrupt :     
    1403             wrapper.printInfo(_("Job %s interrupted by the administrator !") % wrapper.JobId, "warn") 
    1404             retcode = 0 
    1405         except SystemExit, err :     
    1406             retcode = err.code 
    1407         except :     
    14081408            try : 
    1409                 wrapper.crashed("cupspykota backend failed") 
     1409                wrapper.deferredInit() 
     1410                wrapper.initBackendParameters() 
     1411                wrapper.waitForLock() 
     1412                if os.environ.get("PYKOTASTATUS") == "CANCELLED" : 
     1413                    raise KeyboardInterrupt 
     1414                wrapper.saveDatasAndCheckSum() 
     1415                wrapper.preaccounter = openAccounter(wrapper, ispreaccounter=1) 
     1416                wrapper.accounter = openAccounter(wrapper) 
     1417                wrapper.precomputeJobSize() 
     1418                wrapper.exportJobInfo() # exports a first time to give hints to external scripts  
     1419                wrapper.overwriteJobAttributes() 
     1420                wrapper.exportJobInfo() # re-exports in case it was overwritten 
     1421                retcode = wrapper.mainWork() 
     1422            except KeyboardInterrupt :     
     1423                wrapper.printInfo(_("Job %s interrupted by the administrator !") % wrapper.JobId, "warn") 
     1424                retcode = 0 
     1425            except SystemExit, err :     
     1426                retcode = err.code 
    14101427            except :     
    1411                 crashed("cupspykota backend failed") 
    1412             retcode = 1 
    1413         wrapper.clean() 
     1428                try : 
     1429                    wrapper.crashed("cupspykota backend failed") 
     1430                except :     
     1431                    crashed("cupspykota backend failed") 
     1432                retcode = 1 
     1433        finally :         
     1434            wrapper.clean() 
    14141435        sys.exit(retcode)