Yann Leboulanger pushed to branch master at gajim / python-nbxmpp

Commits:

1 changed file:

Changes:

  • nbxmpp/idlequeue.py
    ... ... @@ -21,6 +21,7 @@ objects and be informed about possible IO
    21 21
     from __future__ import unicode_literals
    
    22 22
     
    
    23 23
     import os
    
    24
    +import errno
    
    24 25
     import sys
    
    25 26
     import select
    
    26 27
     import logging
    
    ... ... @@ -59,7 +60,6 @@ PENDING_READ = 3 # waiting read event
    59 60
     PENDING_WRITE           = 4 # waiting write event
    
    60 61
     IS_CLOSED                       = 16 # channel closed
    
    61 62
     
    
    62
    -
    
    63 63
     def get_idlequeue():
    
    64 64
         """
    
    65 65
         Get an appropriate idlequeue
    
    ... ... @@ -353,7 +353,7 @@ class IdleQueue(object):
    353 353
     
    
    354 354
             :param obj: the IdleObject
    
    355 355
             :param writable: True if obj has data to sent
    
    356
    -        :param readable: True if obj expects data to be reiceived
    
    356
    +        :param readable: True if obj expects data to be received
    
    357 357
             """
    
    358 358
             if obj.fd == -1:
    
    359 359
                 return
    
    ... ... @@ -438,16 +438,15 @@ class IdleQueue(object):
    438 438
                 return True
    
    439 439
             try:
    
    440 440
                 waiting_descriptors = self.selector.poll(0)
    
    441
    -        except select.error as e:
    
    441
    +        except OSError as e:
    
    442 442
                 waiting_descriptors = []
    
    443
    -            if e[0] != 4: # interrupt
    
    443
    +            if e.errno != errno.EINTR:
    
    444 444
                     raise
    
    445 445
             for fd, flags in waiting_descriptors:
    
    446 446
                 self._process_events(fd, flags)
    
    447 447
             self._check_time_events()
    
    448 448
             return True
    
    449 449
     
    
    450
    -
    
    451 450
     class SelectIdleQueue(IdleQueue):
    
    452 451
         """
    
    453 452
         Extends IdleQueue to use select.select() for polling
    
    ... ... @@ -456,6 +455,31 @@ class SelectIdleQueue(IdleQueue):
    456 455
         support io_add_watch properly (yet)
    
    457 456
         """
    
    458 457
     
    
    458
    +    def checkQueue(self):
    
    459
    +        """
    
    460
    +        Iterates through all known file descriptors and uses os.stat to check if they're valid.
    
    461
    +        Greatly improves performance if the caller hands us and expects notification on an invalid file handle.
    
    462
    +        """
    
    463
    +        bad_fds=[]
    
    464
    +        union={}
    
    465
    +        union.update(self.write_fds)
    
    466
    +        union.update(self.read_fds)
    
    467
    +        union.update(self.error_fds)
    
    468
    +        for fd in (union.keys()):
    
    469
    +            try:
    
    470
    +                status = os.stat(fd)
    
    471
    +            except OSError as e:
    
    472
    +                # This file descriptor is invalid. Add to list for closure.
    
    473
    +                bad_fds.append(fd)
    
    474
    +
    
    475
    +        for fd in (bad_fds):
    
    476
    +            obj = self.queue.get(fd)
    
    477
    +            if obj is None:
    
    478
    +                self.unplug_idle(fd)
    
    479
    +                return
    
    480
    +            self.remove_timeout(fd)
    
    481
    +            self.unplug_idle(fd)
    
    482
    +
    
    459 483
         def _init_idle(self):
    
    460 484
             """
    
    461 485
             Create a dict, which maps file/pipe/sock descriptor to glib event id
    
    ... ... @@ -466,7 +490,7 @@ class SelectIdleQueue(IdleQueue):
    466 490
     
    
    467 491
         def _add_idle(self, fd, flags):
    
    468 492
             """
    
    469
    -        This method is called when we plug a new idle object. Remove descriptor
    
    493
    +        This method is called when we plug a new idle object. Add descriptor
    
    470 494
             to read/write/error lists, according flags
    
    471 495
             """
    
    472 496
             if flags & 3:
    
    ... ... @@ -494,9 +518,10 @@ class SelectIdleQueue(IdleQueue):
    494 518
             try:
    
    495 519
                 waiting_descriptors = select.select(list(self.read_fds.keys()),
    
    496 520
                         list(self.write_fds.keys()), list(self.error_fds.keys()), 0)
    
    497
    -        except select.error as e:
    
    521
    +        except OSError as e:
    
    498 522
                 waiting_descriptors = ((), (), ())
    
    499
    -            if e[0] != 4: # interrupt
    
    523
    +            if e.errno != errno.EINTR:
    
    524
    +                self.checkQueue()
    
    500 525
                     raise
    
    501 526
             for fd in waiting_descriptors[0]:
    
    502 527
                 q = self.queue.get(fd)