2012-11-12 9 views
7

SfondoOSError: [Errno 11] Risorsa temporaneamente non disponibile. Che cosa causa questo?

Ho due processi Python che devono comunicare tra loro. La permutazione è gestita da una classe chiamata Pipe. Ho creato una classe separata per questo perché la maggior parte delle informazioni che devono essere comunicate si presenta sotto forma di dizionari, quindi Pipe implementa un protocollo piuttosto semplice per farlo.

Ecco il costruttore del tubo:

def __init__(self,sPath): 
    """ 
    create the fifo. if it already exists just associate with it 
    """ 
    self.sPath = sPath 
    if not os.path.exists(sPath): 
     try: 
      os.mkfifo(sPath) 
     except: 
      raise Exception('cannot mkfifo at path \n {0}'.format(sPath)) 
    self.iFH = os.open(sPath,os.O_RDWR | os.O_NONBLOCK) 
    self.iFHBlocking = os.open(sPath,os.O_RDWR) 

Quindi idealmente vorrei solo costruire un tubo in ogni processo con lo stesso percorso e sarebbero in grado di parlare bello.

Ho intenzione di saltare le cose sul protocollo perché penso che sia in gran parte inutile qui.

Tutte le operazioni di lettura e scrittura fanno uso delle seguenti funzioni 'base':

def base_read_blocking(self,iLen): 
    self.lock() 
    lBytes = os.read(self.iFHBlocking,iLen) 
    self.unlock() 
    return lBytes 

def base_read(self,iLen): 
    print('entering base read') 
    self.lock() 
    lBytes = os.read(self.iFH,iLen) 
    self.unlock() 
    print('exiting base read') 
    return lBytes 

def base_write_blocking(self,lBytes): 
    self.lock() 
    safe_write(self.iFHBlocking,lBytes) 
    self.unlock() 

def base_write(self,lBytes): 
    print('entering base write') 
    self.lock() 
    safe_write(self.iFH,lBytes) 
    self.unlock() 
    print('exiting base write') 

safe_write stato suggerito in un altro post

def safe_write(*args, **kwargs): 
    while True: 
     try: 
      return os.write(*args, **kwargs) 
     except OSError as e: 
      if e.errno == 35: 
       import time 
       print(".") 
       time.sleep(0.5) 
      else: 
       raise 

bloccaggio e lo sbloccaggio viene gestito in questo modo:

def lock(self): 
    print('locking...') 
    while True: 
     try: 
      os.mkdir(self.get_lock_dir()) 
      print('...locked') 
      return 
     except OSError as e: 
      if e.errno != 17: 
       raise e 

def unlock(self): 
    try: 
     os.rmdir(self.get_lock_dir()) 
    except OSError as e: 
     if e.errno != 2: 
      raise e 
    print('unlocked') 

Il problema

Questo volte accade:

....in base_read 
lBytes = os.read(self.iFH,iLen) 
OSError: [Errno 11] Resource temporarily unavailable 

A volte va bene.

La soluzione magica

mi sembra di aver fermato il problema si verifichi. Si prega di notare che non sono io che rispondo alla mia stessa domanda. La mia domanda è spiegata nella prossima sezione.

ho cambiato il funzioni di lettura a guardare più come questo e risolto roba:

def base_read(self,iLen): 
    while not self.ready_for_reading(): 
     import time 
     print('.') 
     time.sleep(0.5) 

    lBytes = ''.encode('utf-8') 
    while len(lBytes)<iLen: 
     self.lock() 
     try: 
      lBytes += os.read(self.iFH,iLen) 
     except OSError as e: 
      if e.errno == 11: 
       import time 
       print('.') 
       time.sleep(0.5) 
     finally: 
      self.unlock() 
     return lBytes 


def ready_for_reading(self): 
    lR,lW,lX = select.select([self.iFH,],[],[],self.iTimeout) 
    if not lR: 
     return False 
    lR,lW,lX = select.select([self.iFHBlocking],[],[],self.iTimeout) 
    if not lR: 
     return False 
    return True 

La questione

sto lottando per scoprire esattamente il motivo per cui è temporaneamente non disponibile. I due processi non possono accedere contemporaneamente alla pipe denominata effettiva a causa del meccanismo di blocco (a meno che non mi sbaglio?), Quindi questo è dovuto a qualcosa di più fondamentale di fifos che il mio programma non sta prendendo in considerazione?

Tutto ciò che voglio veramente è una spiegazione ... La soluzione che ho trovato funziona ma sembra magica. Qualcuno può offrire una spiegazione?

sistema

  • Ubuntu 12.04,
  • Python3.2.3

risposta

3

Ho avuto un similar problem with Java prima. Dai un'occhiata alla risposta accettata --- il problema era che stavo creando nuovi thread in un ciclo. Suggerisco di dare un'occhiata al codice che crea la pipe e assicurati di non creare più pipe.

+1

Il punto è creare più pipe. Quindi il processo A crea un tubo e il processo B crea un tubo con lo stesso percorso. Quindi il processo A può dire 'pipe.write (some_dictionary)' e il processo B può dire 'some_dictionary = pipe.read()' – Sheena

+0

Inoltre, se il problema era il numero di cose in esecuzione, allora mettere una chiamata in sleep() non sarebbe Sistemare cose. A meno che non manchi qualcosa ... – Sheena

Problemi correlati