@@ -476,6 +476,57 @@ def test_contextlib(self):
476476        self .assertEqual (None , connection ._Connection__pool .sock )
477477        self .assertEqual (0 , len (connection ._Connection__pool .sockets ))
478478
479+     def  test_interrupt_signal (self ):
480+         """ 
481+         Test fix for PYTHON-294 -- make sure Connection closes its socket if it 
482+         gets an interrupt while waiting to recv() from it. 
483+         """ 
484+         import  pymongo 
485+         import  signal 
486+ 
487+         c  =  get_connection ()
488+         db  =  c .pymongo_test 
489+ 
490+         # A $where clause which takes 1 sec to execute 
491+         where  =  '''function() { 
492+             var d = new Date((new Date()).getTime() + 1*1000); 
493+             while (d > (new Date())) { }; return true; 
494+         }''' 
495+ 
496+         # Need exactly 1 document so find() will execute its $where clause once 
497+         db .drop_collection ('foo' )
498+         db .foo .insert ({'_id' : 1 }, safe = True )
499+ 
500+         # Convert SIGALRM to SIGINT -- it's hard to schedule a SIGINT for 1/2 a 
501+         # second in the future, but easy to schedule SIGALRM. 
502+         def  sigalarm (num , frame ):
503+             import  sys 
504+             raise  KeyboardInterrupt 
505+ 
506+         old_signal_handler  =  signal .signal (signal .SIGALRM , sigalarm )
507+         signal .setitimer (signal .ITIMER_REAL , 0.5 , 0 )
508+         raised  =  False 
509+         try :
510+             # Need list() to actually iterate the cursor and create the 
511+             # cursor on the server; find is lazily evaluated. The find() will 
512+             # be interrupted by sigalarm() raising a KeyboardInterrupt. 
513+             list (db .foo .find ({'$where' : where }))
514+         except  KeyboardInterrupt :
515+             raised  =  True 
516+         finally :
517+             signal .signal (signal .SIGALRM , old_signal_handler )
518+ 
519+         # Can't use self.assertRaises() because it doesn't catch system 
520+         # exceptions 
521+         self .assert_ (raised , "Didn't raise expected KeyboardInterrupt" )
522+ 
523+         # Raises AssertionError due to PYTHON-294 -- Mongo's response to the 
524+         # previous find() is still waiting to be read on the socket, so the 
525+         # request id's don't match. 
526+         self .assertEqual (
527+             [{'_id' : 1 }],
528+             list (db .foo .find ())
529+         )
479530
480531if  __name__  ==  "__main__" :
481532    unittest .main ()
0 commit comments