Komnomnomnom / swigibpy

Third party Interactive Brokers Python API generated from TWS C++ API using SWIG.
http://github.com/Komnomnomnom/swigibpy/
Other
157 stars 35 forks source link

Handle OSError during select #33

Closed sandrinr closed 9 years ago

sandrinr commented 9 years ago

When a user calls tws.eDisconnect() then the poller thread ends up in an exception: OSError: [Errno 9] Bad file descriptor

This happens because once the file descriptor is closed, then select() call in the TWSPoller thread returns with the bad file descriptor error.

With the changes in this pull request, the select() call is surrounded by try catch. Catching an OSError terminates the TWSPoller thread silently instead of printing the exception.

(In the examples this behaviour is not visible because the interpreter normally exits right after tws.eDisconnect() is called and with the termination of the interpreter the poller thread is killed before select returns (because of the daemon=True flag.))

Komnomnomnom commented 9 years ago

Thanks @sandrinr! If you address the couple of comments and squash I will merge.

Once merged I think I'll build on this and add an auto-reconnect so the polling will recommence after a connection is broken.

sandrinr commented 9 years ago

Thanks for the review, @Komnomnomnom . I updated the change to reflect your comments.

I do not want to break of a Python discussion here but I think your comment about the scope of the evts is not correct. Local variables are normally defined in the scope of the defining function. Nevertheless, I moved the code into the else clause ;-).

Komnomnomnom commented 9 years ago

Thanks @sandrinr!

Re that comment, sloppy wording on my part sorry. What I was referring to is that evts will not be defined if an exception is raised on the first iteration of the loop. Not a problem in your proposed code as there is a break when the exception is caught but for maintenance, readability and correctness I feel the else clause is desirable.

An example of what I am talking about (open(42) throws an exception)

In [5]: try:
    foo = open(42)
except:
    pass
print foo
   ...: 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-50c20e2e0474> in <module>()
      3 except:
      4     pass
----> 5 print foo
      6 

NameError: name 'foo' is not defined

In [6]:

vs

In [7]: try:
    foo = open(42)
except:
    pass
else:
    print foo
   ...:         

In [8]: