proper respect for locking with Python GIL, when true threads are enabled

This commit is contained in:
David Rose 2009-12-05 20:40:26 +00:00
parent 62aaf94cb0
commit e4305cf954
2 changed files with 77 additions and 30 deletions

View File

@ -296,7 +296,8 @@ check_datagram() {
if(_native)
_bdc.Flush();
#endif //WANT_NATIVE_NET
while (do_check_datagram()) { //Read a datagram
while (do_check_datagram()) {
if (get_verbose()) {
describe_message(nout, "RECV", _dg);
}
@ -319,9 +320,16 @@ check_datagram() {
// structure, to support legacy code that expects to find it
// there.
if (_python_repository != (PyObject *)NULL) {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
#endif
PyObject *value = PyLong_FromUnsignedLongLong(_msg_sender);
PyObject_SetAttrString(_python_repository, "msgSender", value);
Py_DECREF(value);
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
}
#endif // HAVE_PYTHON
}
@ -728,7 +736,12 @@ do_check_datagram() {
////////////////////////////////////////////////////////////////////
bool CConnectionRepository::
handle_update_field() {
#ifdef HAVE_PYTHON
#ifdef HAVE_PYTHON
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
#endif
PStatTimer timer(_update_pcollector);
unsigned int do_id = _di.get_uint32();
if (_python_repository != (PyObject *)NULL)
@ -768,6 +781,9 @@ handle_update_field() {
if (!cNeverDisable) {
// in quiet zone and distobj is disable-able
// drop update on the floor
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
return true;
}
}
@ -781,11 +797,18 @@ handle_update_field() {
Py_DECREF(distobj);
if (PyErr_Occurred()) {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
return false;
}
}
}
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
#endif // HAVE_PYTHON
return true;
}
@ -804,7 +827,12 @@ handle_update_field() {
////////////////////////////////////////////////////////////////////
bool CConnectionRepository::
handle_update_field_owner() {
#ifdef HAVE_PYTHON
#ifdef HAVE_PYTHON
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
#endif
PStatTimer timer(_update_pcollector);
unsigned int do_id = _di.get_uint32();
if (_python_repository != (PyObject *)NULL) {
@ -855,6 +883,9 @@ handle_update_field_owner() {
Py_DECREF(distobjOV);
if (PyErr_Occurred()) {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
return false;
}
}
@ -891,13 +922,19 @@ handle_update_field_owner() {
Py_DECREF(distobj);
if (PyErr_Occurred()) {
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
return false;
}
}
}
}
#endif // HAVE_PYTHON
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
PyGILState_Release(gstate);
#endif
#endif // HAVE_PYTHON
return true;
}

View File

@ -64,6 +64,16 @@ PUBLISHED:
bool threaded_net = false);
~CConnectionRepository();
// Any methods of this class that acquire _lock (which is most of
// them) *must* be tagged BLOCKING, to avoid risk of a race
// condition in Python when running in true threaded mode. The
// BLOCKING tag releases the Python GIL during the function call,
// and we re-acquire it when needed within these functions to call
// out to Python. If any functions acquire _lock while already
// holding the Python GIL, there could be a deadlock between these
// functions and the ones that are acquiring the GIL while already
// holding _lock.
INLINE DCFile &get_dc_file();
INLINE bool has_owner_view() const;
@ -85,25 +95,25 @@ PUBLISHED:
#endif
#ifdef HAVE_OPENSSL
void set_connection_http(HTTPChannel *channel);
SocketStream *get_stream();
BLOCKING void set_connection_http(HTTPChannel *channel);
BLOCKING SocketStream *get_stream();
#endif
#ifdef HAVE_NET
bool try_connect_net(const URLSpec &url);
BLOCKING bool try_connect_net(const URLSpec &url);
INLINE QueuedConnectionManager &get_qcm();
INLINE ConnectionWriter &get_cw();
INLINE QueuedConnectionReader &get_qcr();
#endif
#ifdef WANT_NATIVE_NET
bool connect_native(const URLSpec &url);
BLOCKING bool connect_native(const URLSpec &url);
INLINE Buffered_DatagramConnection &get_bdc();
#endif
#ifdef SIMULATE_NETWORK_DELAY
void start_delay(double min_delay, double max_delay);
void stop_delay();
BLOCKING void start_delay(double min_delay, double max_delay);
BLOCKING void stop_delay();
#endif
BLOCKING bool check_datagram();
@ -114,37 +124,37 @@ PUBLISHED:
#endif
#endif
INLINE void get_datagram(Datagram &dg);
INLINE void get_datagram_iterator(DatagramIterator &di);
INLINE CHANNEL_TYPE get_msg_channel(int offset = 0) const;
INLINE int get_msg_channel_count() const;
INLINE CHANNEL_TYPE get_msg_sender() const;
BLOCKING INLINE void get_datagram(Datagram &dg);
BLOCKING INLINE void get_datagram_iterator(DatagramIterator &di);
BLOCKING INLINE CHANNEL_TYPE get_msg_channel(int offset = 0) const;
BLOCKING INLINE int get_msg_channel_count() const;
BLOCKING INLINE CHANNEL_TYPE get_msg_sender() const;
// INLINE unsigned char get_sec_code() const;
INLINE unsigned int get_msg_type() const;
BLOCKING INLINE unsigned int get_msg_type() const;
INLINE static const string &get_overflow_event_name();
bool is_connected();
BLOCKING bool is_connected();
BLOCKING bool send_datagram(const Datagram &dg);
INLINE void set_want_message_bundling(bool flag);
INLINE bool get_want_message_bundling() const;
BLOCKING INLINE void set_want_message_bundling(bool flag);
BLOCKING INLINE bool get_want_message_bundling() const;
INLINE void set_in_quiet_zone(bool flag);
INLINE bool get_in_quiet_zone() const;
BLOCKING INLINE void set_in_quiet_zone(bool flag);
BLOCKING INLINE bool get_in_quiet_zone() const;
void start_message_bundle();
INLINE bool is_bundling_messages() const;
void send_message_bundle(unsigned int channel, unsigned int sender_channel);
void abandon_message_bundles();
void bundle_msg(const Datagram &dg);
BLOCKING void start_message_bundle();
BLOCKING INLINE bool is_bundling_messages() const;
BLOCKING void send_message_bundle(unsigned int channel, unsigned int sender_channel);
BLOCKING void abandon_message_bundles();
BLOCKING void bundle_msg(const Datagram &dg);
BLOCKING bool consider_flush();
BLOCKING bool flush();
void disconnect();
void shutdown();
BLOCKING void disconnect();
BLOCKING void shutdown();
INLINE void set_simulated_disconnect(bool simulated_disconnect);
INLINE bool get_simulated_disconnect() const;