Skip to content

Commit 18a205d

Browse files
committed
do NOT use PyGILState_GetThisThreadState, it may deadlock. use other CPython API to fish the right thread state
1 parent acc3f1b commit 18a205d

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
name='vmprof',
7979
author='vmprof team',
8080
author_email='fijal@baroquesoftware.com',
81-
version="0.4.2.dev0",
81+
version="0.4.2.dev1",
8282
packages=find_packages(),
8383
description="Python's vmprof client",
8484
long_description='See https://vmprof.readthedocs.org/',

src/vmprof.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ int IS_VMPROF_EVAL(void * ptr);
5454
// for cpython
5555
#include "_vmprof.h"
5656
#include <Python.h>
57+
#include <pythread.h>
5758
#include <frameobject.h>
5859
#define PY_STACK_FRAME_T PyFrameObject
5960
#define PY_EVAL_RETURN_T PyObject

src/vmprof_main.h

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
*
1313
* Tested only on gcc, linux, x86_64.
1414
*
15-
* Copyright (C) 2014-2015
15+
* Copyright (C) 2014-2017
1616
* Antonio Cuni - anto.cuni@gmail.com
1717
* Maciej Fijalkowski - fijall@gmail.com
1818
* Armin Rigo - arigo@tunes.org
19+
* Richard Plangger - planrichi@gmail.com
1920
*
2021
*/
2122

@@ -145,6 +146,35 @@ int _vmprof_sample_stack(struct profbuf_s *p, PY_THREAD_STATE_T * tstate, uconte
145146
return 1;
146147
}
147148

149+
#ifndef RPYTHON_VMPROF
150+
static PY_THREAD_STATE_T * _get_pystate_for_this_thread(void) {
151+
// see issue 116 on github.com/vmprof/vmprof-python.
152+
// PyGILState_GetThisThreadState(); can hang forever
153+
//
154+
PyInterpreterState * istate;
155+
PyThreadState * state;
156+
long mythread_id;
157+
158+
istate = PyInterpreterState_Head();
159+
if (istate == NULL) {
160+
return NULL;
161+
}
162+
mythread_id = PyThread_get_thread_ident();
163+
// fish fish fish, it will NOT lock the keymutex in pythread
164+
do {
165+
state = PyInterpreterState_ThreadHead(istate);
166+
do {
167+
if (state->thread_id == mythread_id) {
168+
return state;
169+
}
170+
} while ((state = PyThreadState_Next(state)) != NULL);
171+
} while ((istate = PyInterpreterState_Next(istate)) != NULL);
172+
173+
// uh? not found?
174+
return NULL;
175+
}
176+
#endif
177+
148178
static void sigprof_handler(int sig_nr, siginfo_t* info, void *ucontext)
149179
{
150180
int commit;
@@ -167,7 +197,7 @@ static void sigprof_handler(int sig_nr, siginfo_t* info, void *ucontext)
167197
int fault_code = setjmp(restore_point);
168198
if (fault_code == 0) {
169199
pthread_self();
170-
tstate = PyGILState_GetThisThreadState();
200+
tstate = _get_pystate_for_this_thread();
171201
} else {
172202
signal(SIGSEGV, prevhandler);
173203
__sync_lock_release(&spinlock);

0 commit comments

Comments
 (0)