Show
Ignore:
Timestamp:
05/25/04 00:45:49 (20 years ago)
Author:
jalet
Message:

New 'enforcement' directive added
Polling loop improvements

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r1494 r1495  
    2424# 
    2525# $Log$ 
     26# Revision 1.49  2004/05/24 22:45:48  jalet 
     27# New 'enforcement' directive added 
     28# Polling loop improvements 
     29# 
    2630# Revision 1.48  2004/05/24 14:36:24  jalet 
    2731# Revert to old polling loop. Will need optimisations 
     
    252256             
    253257            # checks the user's quota 
     258            self.softwareJobPrice = userpquota.computeJobPrice(self.softwareJobSize) 
    254259            action = self.warnUserPQuota(userpquota) 
    255260             
     
    311316        return retcode     
    312317                
    313     def setNonBlocking(self, fno) : 
    314         """Sets a file handle to be non-blocking.""" 
    315         flags = fcntl.fcntl(fno, fcntl.F_GETFL, 0) 
    316         fcntl.fcntl(fno, fcntl.F_SETFL, flags | os.O_NONBLOCK) 
    317  
    318318    def unregisterFileNo(self, pollobj, fileno) :                 
    319319        """Removes a file handle from the polling object.""" 
     
    327327            self.logdebug("File number %s unregistered from polling object." % fileno) 
    328328             
    329     def formatFileEvent(self, fd, mask, ins, outs) :         
     329    def formatFileEvent(self, fd, mask) :         
    330330        """Formats file debug info.""" 
    331         try : 
    332             name = ins.get(fd, outs.get(fd))["name"] 
    333         except KeyError :     
    334             self.logdebug("File %s not found in %s or %s" % (fd, repr(ins), repr(outs))) 
    335         else :     
    336             maskval = [] 
    337             if mask & select.POLLIN : 
    338                 maskval.append("POLLIN") 
    339             if mask & select.POLLOUT : 
    340                 maskval.append("POLLOUT") 
    341             if mask & select.POLLPRI : 
    342                 maskval.append("POLLPRI") 
    343             if mask & select.POLLERR : 
    344                 maskval.append("POLLERR") 
    345             if mask & select.POLLHUP : 
    346                 maskval.append("POLLHUP") 
    347             if mask & select.POLLNVAL : 
    348                 maskval.append("POLLNVAL") 
    349             return "%s (%s)" % (name, " | ".join(maskval)) 
     331        maskval = [] 
     332        if mask & select.POLLIN : 
     333            maskval.append("POLLIN") 
     334        if mask & select.POLLOUT : 
     335            maskval.append("POLLOUT") 
     336        if mask & select.POLLPRI : 
     337            maskval.append("POLLPRI") 
     338        if mask & select.POLLERR : 
     339            maskval.append("POLLERR") 
     340        if mask & select.POLLHUP : 
     341            maskval.append("POLLHUP") 
     342        if mask & select.POLLNVAL : 
     343            maskval.append("POLLNVAL") 
     344        return "%s (%s)" % (fd, " | ".join(maskval)) 
    350345         
    351346    def handleData(self) :                     
     
    378373        if self.preserveinputfile is None : 
    379374            # this is not a real file, we read the job's data 
    380             # from stdin  
     375            # from our temporary file which is a copy of stdin  
    381376            infno = self.jobdatastream.fileno() 
    382377            self.jobdatastream.seek(0) 
     
    389384            endinput = 1 
    390385         
    391         self.logdebug("Catching SIGTERM.") 
     386        self.logdebug("Capturing SIGTERM events.") 
    392387        signal.signal(signal.SIGTERM, self.sigterm_handler) 
    393388         
     389        self.logdebug("Entering streams polling loop...") 
     390        MEGABYTE = 1024*1024 
    394391        killed = 0 
    395         self.logdebug("Entering streams polling loop...") 
    396392        status = -1 
    397         while status == -1 : 
     393        while (status == -1) and (not killed) and not (inputclosed and outputclosed) : 
    398394            # First check if original backend is still alive 
    399395            status = subprocess.poll() 
     
    404400                try : 
    405401                    os.kill(subprocess.pid, signal.SIGTERM) 
     402                except OSError, msg : # ignore but logs if process was already killed. 
     403                    self.logdebug("Error while sending signal to pid %s" % subprocess.pid) 
     404                else :     
    406405                    self.logger.log_message(_("SIGTERM was sent to real backend %s (pid: %s)") % (realbackend, subprocess.pid), "info") 
    407406                    killed = 1 
    408                 except : # ignore if process was already killed. 
    409                     pass 
    410407             
    411408            # In any case, deal with any remaining I/O 
    412409            availablefds = pollster.poll(5000) 
    413             for (fd, mask) in availablefds : 
    414                 # self.logdebug("file: %i    mask: %04x" % (fd, mask)) 
    415                 try : 
    416                     if mask & select.POLLOUT : 
    417                         # We can write 
    418                         if fd == tocfno : 
    419                             if indata : 
    420                                 os.write(fd, indata)     
    421                                 try : 
    422                                     os.fsync(fd) 
    423                                 except OSError : 
    424                                     pass 
    425                                 indata = "" 
    426                             if endinput :     
    427                                 self.unregisterFileNo(pollster, tocfno)         
    428                                 self.logdebug("Closing real backend's stdin.") 
    429                                 os.close(tocfno) 
    430                                 inputclosed = 1 
    431                         elif fd == stderrfno : 
    432                             if outdata : 
    433                                 os.write(fd, outdata) 
    434                                 try : 
    435                                     os.fsync(fd) 
    436                                 except OSError :     
    437                                     pass 
    438                                 outdata = "" 
    439                             if endoutput :     
    440                                 self.unregisterFileNo(pollster, stderrfno)         
    441                                 outputclosed = 1 
    442                     if (mask & select.POLLIN) or (mask & select.POLLPRI) :      
    443                         # We have something to read 
    444                         try : 
    445                             data = os.read(fd, 256 * 1024) 
    446                         except OSError, msg :     
    447                             self.logdebug("Error while reading file %s : %s" % (fd, msg)) 
    448                         else : 
     410            if not availablefds : 
     411                self.logdebug("Nothing to do, sleeping a bit...") 
     412                time.sleep(0.01) # give some time to the system 
     413            else : 
     414                for (fd, mask) in availablefds : 
     415                    # self.logdebug(self.formatFileEvent(fd, mask)) 
     416                    try : 
     417                        if mask & select.POLLOUT : 
     418                            # We can write 
     419                            if fd == tocfno : 
     420                                if indata : 
     421                                    try : 
     422                                        os.write(fd, indata)     
     423                                    except IOError, msg :     
     424                                        self.logdebug("Error while writing to real backend's stdin %s : %s" % (fd, msg)) 
     425                                    else :     
     426                                        indata = "" 
     427                                if endinput :     
     428                                    self.unregisterFileNo(pollster, tocfno)         
     429                                    self.logdebug("Closing real backend's stdin.") 
     430                                    os.close(tocfno) 
     431                                    inputclosed = 1 
     432                            elif fd == stderrfno : 
     433                                if outdata : 
     434                                    try : 
     435                                        os.write(fd, outdata) 
     436                                    except IOError, msg :     
     437                                        self.logdebug("Error while writing to CUPS back channel (stderr) %s : %s" % (fd, msg)) 
     438                                    else : 
     439                                        outdata = "" 
     440                                if endoutput :     
     441                                    self.unregisterFileNo(pollster, stderrfno)         
     442                                    outputclosed = 1 
     443                        if mask & (select.POLLIN | select.POLLPRI) :      
     444                            # We have something to read 
     445                            try : 
     446                                data = os.read(fd, MEGABYTE) 
     447                            except (IOError, OSError), msg :     
     448                                self.logdebug("Error while reading file %s : %s" % (fd, msg)) 
     449                            else : 
     450                                if fd == infno : 
     451                                    indata += data 
     452                                    if not data :    # If yes, then no more input data 
     453                                        self.unregisterFileNo(pollster, infno) 
     454                                        self.logdebug("Input data ends.") 
     455                                        endinput = 1 # this happens with real files. 
     456                                elif fd == fromcfno : 
     457                                    outdata += data 
     458                        if mask & (select.POLLHUP | select.POLLERR) : 
     459                            # Treat POLLERR as an EOF. 
     460                            # Some standard I/O stream has no more datas 
     461                            self.unregisterFileNo(pollster, fd) 
    449462                            if fd == infno : 
    450                                 indata += data 
    451                                 if not data :    # If yes, then no more input data 
    452                                     self.unregisterFileNo(pollster, infno) 
    453                                     self.logdebug("Input data ends.") 
    454                                     endinput = 1 # this happens with real files. 
    455                             elif fd == fromcfno : 
    456                                 outdata += data 
    457                     if (mask & select.POLLHUP) or (mask & select.POLLERR) : 
    458                         # I've never seen POLLERR myself, but this probably 
    459                         # can't hurt to treat an error condition just like  
    460                         # an EOF. 
    461                         #  
    462                         # Some standard I/O stream has no more datas 
    463                         self.unregisterFileNo(pollster, fd) 
    464                         if fd == infno : 
    465                             # Here we are in the case where the input file is stdin. 
    466                             # which has no more data to be read. 
    467                             self.logdebug("Input data ends.") 
    468                             endinput = 1 
    469                         elif fd == fromcfno :     
    470                             # We are no more interested in this file descriptor         
    471                             self.logdebug("Closing real backend's stdout+stderr.") 
    472                             os.close(fromcfno) 
    473                             endoutput = 1 
    474                 except IOError :             
    475                     pass # we got signalled during an I/O it seems 
    476             if killed or (inputclosed and outputclosed) : 
    477                 break 
     463                                # Here we are in the case where the input file is stdin. 
     464                                # which has no more data to be read. 
     465                                self.logdebug("Input data ends.") 
     466                                endinput = 1 
     467                            elif fd == fromcfno :     
     468                                # We are no more interested in this file descriptor         
     469                                self.logdebug("Closing real backend's stdout+stderr.") 
     470                                os.close(fromcfno) 
     471                                endoutput = 1 
     472                                 
     473                        if mask & select.POLLNVAL :         
     474                            self.logdebug("File %s was closed. Unregistering from polling object." % fd) 
     475                            self.unregisterFileNo(pollster, fd) 
     476                    except IOError, msg :             
     477                        self.logdebug("Got an IOError : %s" % msg) # we got signalled during an I/O 
    478478                 
    479479        # We must close the real backend's input stream 
     
    491491            # we exited the loop before the real backend exited 
    492492            # now we have to wait for it to finish and get its status 
     493            self.logdebug("Waiting for real backend to exit...") 
    493494            try : 
    494495                status = subprocess.wait()