@@ -34,20 +34,33 @@ map<CPushConsumer *, PyObject *> g_CallBackMap;
3434
3535class PyThreadStateLock {
3636public:
37- PyThreadStateLock (void ) {
37+ PyThreadStateLock () {
3838 state = PyGILState_Ensure ();
3939 }
4040
41- ~PyThreadStateLock (void ) {
42- if (state == PyGILState_LOCKED) {
43- PyGILState_Release (state);
44- }
41+ ~PyThreadStateLock () {
42+ // NOTE: must paired with PyGILState_Ensure, otherwise it will cause deadlock!!!
43+ PyGILState_Release (state);
4544 }
4645
4746private:
4847 PyGILState_STATE state;
4948};
5049
50+ class PyThreadStateUnlock {
51+ public:
52+ PyThreadStateUnlock () : _save(NULL ) {
53+ Py_UNBLOCK_THREADS
54+ }
55+
56+ ~PyThreadStateUnlock () {
57+ Py_BLOCK_THREADS
58+ }
59+
60+ private:
61+ PyThreadState *_save;
62+ };
63+
5164#ifdef __cplusplus
5265extern " C" {
5366#endif
@@ -146,9 +159,7 @@ const char *PyGetSendResultMsgID(CSendResult &sendResult) {
146159}
147160// consumer
148161void *PyCreatePushConsumer (const char *groupId) {
149- // Py_Initialize();
150- PyEval_InitThreads ();
151- // PyEval_ReleaseThread(PyThreadState_Get());
162+ PyEval_InitThreads (); // ensure create GIL, for call Python callback from C.
152163 return (void *) CreatePushConsumer (groupId);
153164}
154165int PyDestroyPushConsumer (void *consumer) {
@@ -158,10 +169,8 @@ int PyStartPushConsumer(void *consumer) {
158169 return StartPushConsumer ((CPushConsumer *) consumer);
159170}
160171int PyShutdownPushConsumer (void *consumer) {
161- int ret = ShutdownPushConsumer ((CPushConsumer *) consumer);
162- // PyGILState_Ensure();
163- // Py_Finalize();
164- return ret;
172+ PyThreadStateUnlock PyThreadUnlock; // ShutdownPushConsumer is a block call, ensure thread don't hold GIL.
173+ return ShutdownPushConsumer ((CPushConsumer *) consumer);
165174}
166175int PySetPushConsumerNameServerAddress (void *consumer, const char *namesrv) {
167176 return SetPushConsumerNameServerAddress ((CPushConsumer *) consumer, namesrv);
@@ -212,7 +221,7 @@ int PySetPushConsumerSessionCredentials(void *consumer, const char *accessKey, c
212221}
213222
214223// push consumer
215- int PySetPullConsumerNameServerDomain (void *consumer, const char *domain){
224+ int PySetPullConsumerNameServerDomain (void *consumer, const char *domain) {
216225 return SetPullConsumerNameServerDomain ((CPullConsumer *) consumer, domain);
217226}
218227// version
0 commit comments