diff --git a/coverage/ctracer/tracer.c b/coverage/ctracer/tracer.c index c05dff643..ed05a42d0 100644 --- a/coverage/ctracer/tracer.c +++ b/coverage/ctracer/tracer.c @@ -818,7 +818,7 @@ CTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unuse return RET_OK; #endif - if (!self->started) { + if (!atomic_load(&self->started)) { /* If CTracer.stop() has been called from another thread, the tracer is still active in the current thread. Let's deactivate ourselves now. */ @@ -848,7 +848,7 @@ CTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unuse Py_DECREF(ascii); #endif - self->activity = TRUE; + atomic_store(&self->activity, TRUE); switch (what) { case PyTrace_CALL: @@ -981,9 +981,10 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds) static PyObject * CTracer_start(CTracer *self, PyObject *args_unused) { + assert(atomic_load(&self->started) == FALSE); PyEval_SetTrace((Py_tracefunc)CTracer_trace, (PyObject*)self); - self->started = TRUE; self->tracing_arcs = self->trace_arcs && PyObject_IsTrue(self->trace_arcs); + atomic_store(&self->started, TRUE); /* start() returns a trace function usable with sys.settrace() */ Py_INCREF(self); @@ -993,13 +994,11 @@ CTracer_start(CTracer *self, PyObject *args_unused) static PyObject * CTracer_stop(CTracer *self, PyObject *args_unused) { - if (self->started) { - /* Set the started flag only. The actual call to - PyEval_SetTrace(NULL, NULL) is delegated to the callback - itself to ensure that it called from the right thread. - */ - self->started = FALSE; - } + /* Set the started flag only. The actual call to + PyEval_SetTrace(NULL, NULL) is delegated to the callback + itself to ensure that it called from the right thread. + */ + atomic_store(&self->started, FALSE); Py_RETURN_NONE; } @@ -1007,7 +1006,7 @@ CTracer_stop(CTracer *self, PyObject *args_unused) static PyObject * CTracer_activity(CTracer *self, PyObject *args_unused) { - if (self->activity) { + if (atomic_load(&self->activity)) { Py_RETURN_TRUE; } else { @@ -1018,7 +1017,7 @@ CTracer_activity(CTracer *self, PyObject *args_unused) static PyObject * CTracer_reset_activity(CTracer *self, PyObject *args_unused) { - self->activity = FALSE; + atomic_store(&self->activity, FALSE); Py_RETURN_NONE; } diff --git a/coverage/ctracer/tracer.h b/coverage/ctracer/tracer.h index b00134de9..7f3f85679 100644 --- a/coverage/ctracer/tracer.h +++ b/coverage/ctracer/tracer.h @@ -32,11 +32,11 @@ typedef struct CTracer { PyObject * disable_plugin; /* Has the tracer been started? */ - BOOL started; + _Atomic BOOL started; /* Are we tracing arcs, or just lines? */ BOOL tracing_arcs; /* Have we had any activity? */ - BOOL activity; + _Atomic BOOL activity; /* The current dynamic context. */ PyObject * context; diff --git a/coverage/ctracer/util.h b/coverage/ctracer/util.h index 94591e0d2..cef8e0c4d 100644 --- a/coverage/ctracer/util.h +++ b/coverage/ctracer/util.h @@ -5,6 +5,7 @@ #define _COVERAGE_UTIL_H #include +#include /* Compile-time debugging helpers */ #undef WHAT_LOG /* Define to log the WHAT params in the trace function. */ diff --git a/setup.py b/setup.py index 92fad6502..45c501adf 100644 --- a/setup.py +++ b/setup.py @@ -155,6 +155,11 @@ def run(self): def build_extension(self, ext): """Wrap `build_extension` with `BuildFailed`.""" + if self.compiler.compiler_type == "msvc": + ext.extra_compile_args = (ext.extra_compile_args or []) + [ + "/std:c11", + "/experimental:c11atomics", + ] try: # Uncomment to test compile failure handling: # raise errors.CCompilerError("OOPS")