stellarbit/aioping

Socket issues

Closed this issue · 5 comments

This is the traceback I get due to line 179 in init.py, my_socket.close()
If I remove this line, this error goes away, but then I get a different error since the socket doesn't get closed on timeouts.

Traceback (most recent call last):                                                                                                                                                                                                                
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 43, in run                                                                                                                                                                        
    return loop.run_until_complete(main)                                                                                                                                                                                                          
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 566, in run_until_complete                                                                                                                                                    
    self.run_forever()                                                                                                                                                                                                                            
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 534, in run_forever                                                                                                                                                           
    self._run_once()                                                                                                                                                                                                                              
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 1735, in _run_once                                                                                                                                                            
    event_list = self._selector.select(timeout)                                                                                                                                                                                                   
  File "C:\Program Files\Python37\lib\selectors.py", line 323, in select                                                                                                                                                                          
    r, w, _ = self._select(self._readers, self._writers, [], timeout)                                                                                                                                                                             
  File "C:\Program Files\Python37\lib\selectors.py", line 314, in _select                                                                                                                                                                         
    r, w, x = select.select(r, w, w, timeout)                                                                                                                                                                                                     
OSError: [WinError 10038] An operation was attempted on something that is not a socket                                                                                                                                                            
                                                                                                                                                                                                                                                  
During handling of the above exception, another exception occurred:                                                                                                                                                                               
                                                                                                                                                                                                                                                  
Traceback (most recent call last):                                                                                                                                                                                                                
  File "ping_testing.py", line 86, in <module>                                                                                                                                                                                                    
    asyncio.run(main_loop())                                                                                                                                                                                                                      
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 46, in run                                                                                                                                                                        
    _cancel_all_tasks(loop)                                                                                                                                                                                                                       
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 62, in _cancel_all_tasks                                                                                                                                                          
    tasks.gather(*to_cancel, loop=loop, return_exceptions=True))                                                                                                                                                                                  
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 566, in run_until_complete                                                                                                                                                    
    self.run_forever()                                                                                                                                                                                                                            
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 534, in run_forever                                                                                                                                                           
    self._run_once()                                                                                                                                                                                                                              
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 1735, in _run_once                                                                                                                                                            
    event_list = self._selector.select(timeout)                                                                                                                                                                                                   
  File "C:\Program Files\Python37\lib\selectors.py", line 323, in select                                                                                                                                                                          
    r, w, _ = self._select(self._readers, self._writers, [], timeout)                                                                                                                                                                             
  File "C:\Program Files\Python37\lib\selectors.py", line 314, in _select                                                                                                                                                                         
    r, w, x = select.select(r, w, w, timeout)                                                                                                                                                                                                     
OSError: [WinError 10038] An operation was attempted on something that is not a socket

Originally posted by @Crypto-Spartan in #9 (comment)

If I comment out my_socket.close() this is the error I get after a few pings:

Traceback (most recent call last):                                                                                                                                                                                                                
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 43, in run                                                                                                                                                                        
    return loop.run_until_complete(main)                                                                                                                                                                                                          
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 566, in run_until_complete                                                                                                                                                    
    self.run_forever()                                                                                                                                                                                                                            
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 534, in run_forever                                                                                                                                                           
    self._run_once()                                                                                                                                                                                                                              
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 1735, in _run_once                                                                                                                                                            
    event_list = self._selector.select(timeout)                                                                                                                                                                                                   
  File "C:\Program Files\Python37\lib\selectors.py", line 323, in select                                                                                                                                                                          
    r, w, _ = self._select(self._readers, self._writers, [], timeout)                                                                                                                                                                             
  File "C:\Program Files\Python37\lib\selectors.py", line 314, in _select                                                                                                                                                                         
    r, w, x = select.select(r, w, w, timeout)                                                                                                                                                                                                     
ValueError: too many file descriptors in select()                                                                                                                                                                                                 
                                                                                                                                                                                                                                                  
During handling of the above exception, another exception occurred:                                                                                                                                                                               
                                                                                                                                                                                                                                                  
Traceback (most recent call last):                                                                                                                                                                                                                
  File "ping_testing.py", line 86, in <module>                                                                                                                                                                                                    
    asyncio.run(main_loop())                                                                                                                                                                                                                      
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 46, in run                                                                                                                                                                        
    _cancel_all_tasks(loop)                                                                                                                                                                                                                       
  File "C:\Program Files\Python37\lib\asyncio\runners.py", line 62, in _cancel_all_tasks                                                                                                                                                          
    tasks.gather(*to_cancel, loop=loop, return_exceptions=True))                                                                                                                                                                                  
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 566, in run_until_complete                                                                                                                                                    
    self.run_forever()                                                                                                                                                                                                                            
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 534, in run_forever                                                                                                                                                           
    self._run_once()                                                                                                                                                                                                                              
  File "C:\Program Files\Python37\lib\asyncio\base_events.py", line 1735, in _run_once                                                                                                                                                            
    event_list = self._selector.select(timeout)                                                                                                                                                                                                   
  File "C:\Program Files\Python37\lib\selectors.py", line 323, in select                                                                                                                                                                          
    r, w, _ = self._select(self._readers, self._writers, [], timeout)                                                                                                                                                                             
  File "C:\Program Files\Python37\lib\selectors.py", line 314, in _select                                                                                                                                                                         
    r, w, x = select.select(r, w, w, timeout)                                                                                                                                                                                                     
ValueError: too many file descriptors in select()

As you can see here and here, this issue is present since there is a limitation in how many sockets can be open at once. I attempted to remedy the issue with asyncio.Semaphore, but it did not work, as the sockets from the timed out pings still were not closed, even though I would only ping 64 addresses at a time. Even when I limited Semaphore to 10 addresses at once, the ValueError was still present.

I like the idea of attempting to close the socket as such in this commit, but it ultimately breaks things somehow and I can't quite figure out how to fix it. I'm hoping that @anton-belousov can provide some insight

So far, the only fix for this issue that I've found is to create new event loops for different threads, and limit each thread to ping 255 addresses at once, since this is within the limitation of how many sockets that can be open at once. This fix requires my_socket.close() on line 179 to be commented out in order for it to work.

Unfortunately, this doesn't resolve the underlying issue at all, since the socket technically isn't closed by the script. This is just a workaround to keep opening new sockets since they're on separate event loops.

This is the code for both of the scripts I'm attempting to use: https://github.com/Crypto-Spartan/aioping_testing

@Crypto-Spartan may I ask you to check if the issue is fixed in this branch, please?
issue-17-fix

I tested it on Windows 10 & Python 3.7 and could reproduce the issue, but after the fix in that branch above it seems to work just fine. The problem was not reproducing on Windows 10 & Python 3.8 or on Linux or Mac OS X. The fixed version seems to work anywhere now.

@anton-belousov It's fixed! Thank you!