diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2015-02-26 06:34:03 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2015-02-26 06:34:03 -0500 |
commit | 66d3413c85f788a98c161127a51b3b21f4fcce2f (patch) | |
tree | 222d799f99173d09535eadf86e601317bb5383cc /coverage/tracer.c | |
parent | 3e993b55885d4c10fad14475e67e4fc204691aa1 (diff) | |
download | python-coveragepy-git-66d3413c85f788a98c161127a51b3b21f4fcce2f.tar.gz |
Handle exceptions from dynamic_source_filename.
This required disabling plugins from the C tracer.
Diffstat (limited to 'coverage/tracer.c')
-rw-r--r-- | coverage/tracer.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/coverage/tracer.c b/coverage/tracer.c index 56703264..c63d3975 100644 --- a/coverage/tracer.c +++ b/coverage/tracer.c @@ -21,7 +21,9 @@ #define MyText_Type PyUnicode_Type #define MyText_AS_BYTES(o) PyUnicode_AsASCIIString(o) -#define MyText_AS_STRING(o) PyBytes_AS_STRING(o) +#define MyBytes_AS_STRING(o) PyBytes_AS_STRING(o) +#define MyText_AsString(o) PyUnicode_AsUTF8(o) +#define MyText_FromFormat PyUnicode_FromFormat #define MyInt_FromInt(i) PyLong_FromLong((long)i) #define MyInt_AsInt(o) (int)PyLong_AsLong(o) @@ -31,7 +33,9 @@ #define MyText_Type PyString_Type #define MyText_AS_BYTES(o) (Py_INCREF(o), o) -#define MyText_AS_STRING(o) PyString_AS_STRING(o) +#define MyBytes_AS_STRING(o) PyString_AS_STRING(o) +#define MyText_AsString(o) PyString_AsString(o) +#define MyText_FromFormat PyUnicode_FromFormat #define MyInt_FromInt(i) PyInt_FromLong((long)i) #define MyInt_AsInt(o) (int)PyInt_AsLong(o) @@ -298,7 +302,7 @@ showlog(int depth, int lineno, PyObject * filename, const char * msg) } if (filename) { PyObject *ascii = MyText_AS_BYTES(filename); - printf(" %s", MyText_AS_STRING(ascii)); + printf(" %s", MyBytes_AS_STRING(ascii)); Py_DECREF(ascii); } if (msg) { @@ -457,7 +461,9 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) PyObject * tracename = NULL; PyObject * disposition = NULL; PyObject * disp_trace = NULL; - PyObject * disp_file_tracer = NULL; + PyObject * file_tracer = NULL; + PyObject * plugin = NULL; + PyObject * plugin_name = NULL; PyObject * has_dynamic_filename = NULL; /* Borrowed references. */ @@ -507,10 +513,20 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) if (tracename == NULL) { goto error; } - disp_file_tracer = PyObject_GetAttrString(disposition, "file_tracer"); - if (disp_file_tracer == NULL) { + file_tracer = PyObject_GetAttrString(disposition, "file_tracer"); + if (file_tracer == NULL) { goto error; } + if (file_tracer != Py_None) { + plugin = PyObject_GetAttrString(file_tracer, "_coverage_plugin"); + if (plugin == NULL) { + goto error; + } + plugin_name = PyObject_GetAttrString(plugin, "_coverage_plugin_name"); + if (plugin_name == NULL) { + goto error; + } + } has_dynamic_filename = PyObject_GetAttrString(disposition, "has_dynamic_filename"); if (has_dynamic_filename == NULL) { goto error; @@ -518,11 +534,42 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) if (has_dynamic_filename == Py_True) { PyObject * next_tracename = NULL; next_tracename = PyObject_CallMethod( - disp_file_tracer, "dynamic_source_filename", + file_tracer, "dynamic_source_filename", "OO", tracename, frame ); if (next_tracename == NULL) { - goto error; + /* An exception from the function. Alert the user with a + * warning and a traceback. + */ + PyObject * ignored = NULL; + PyObject * msg = NULL; + + msg = MyText_FromFormat( + "Disabling plugin '%s' due to an exception:", + MyText_AsString(plugin_name) + ); + if (msg == NULL) { + goto error; + } + ignored = PyObject_CallFunctionObjArgs(self->warn, msg, NULL); + if (ignored == NULL) { + goto error; + } + Py_DECREF(msg); + Py_DECREF(ignored); + + PyErr_Print(); + + /* Disable the plugin for future files, and stop tracing this file. */ + if (PyObject_SetAttrString(plugin, "_coverage_enabled", Py_False) < 0) { + goto error; + } + if (PyObject_SetAttrString(disposition, "trace", Py_False) < 0) { + goto error; + } + + /* Because we handled the error, goto ok. */ + goto ok; } Py_DECREF(tracename); tracename = next_tracename; @@ -556,7 +603,6 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) if (tracename != Py_None) { PyObject * file_data = PyDict_GetItem(self->data, tracename); - PyObject * disp_plugin_name = NULL; if (file_data == NULL) { file_data = PyDict_New(); @@ -570,13 +616,8 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) } /* If the disposition mentions a plugin, record that. */ - if (disp_file_tracer != Py_None) { - disp_plugin_name = PyObject_GetAttrString(disp_file_tracer, "_coverage_plugin_name"); - if (disp_plugin_name == NULL) { - goto error; - } - ret2 = PyDict_SetItem(self->plugin_data, tracename, disp_plugin_name); - Py_DECREF(disp_plugin_name); + if (file_tracer != Py_None) { + ret2 = PyDict_SetItem(self->plugin_data, tracename, plugin_name); if (ret2 < 0) { goto error; } @@ -584,7 +625,7 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) } self->cur_entry.file_data = file_data; - self->cur_entry.file_tracer = disp_file_tracer; + self->cur_entry.file_tracer = file_tracer; /* Make the frame right in case settrace(gettrace()) happens. */ Py_INCREF(self); @@ -599,13 +640,16 @@ CTracer_handle_call(CTracer *self, PyFrameObject *frame) self->cur_entry.last_line = -1; +ok: ret = RET_OK; error: Py_XDECREF(tracename); Py_XDECREF(disposition); Py_XDECREF(disp_trace); - Py_XDECREF(disp_file_tracer); + Py_XDECREF(file_tracer); + Py_XDECREF(plugin); + Py_XDECREF(plugin_name); Py_XDECREF(has_dynamic_filename); return ret; @@ -742,14 +786,14 @@ CTracer_trace(CTracer *self, PyFrameObject *frame, int what, PyObject *arg_unuse #if WHAT_LOG if (what <= sizeof(what_sym)/sizeof(const char *)) { ascii = MyText_AS_BYTES(frame->f_code->co_filename); - printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(ascii), frame->f_lineno); + printf("trace: %s @ %s %d\n", what_sym[what], MyBytes_AS_STRING(ascii), frame->f_lineno); Py_DECREF(ascii); } #endif #if TRACE_LOG ascii = MyText_AS_BYTES(frame->f_code->co_filename); - if (strstr(MyText_AS_STRING(ascii), start_file) && frame->f_lineno == start_line) { + if (strstr(MyBytes_AS_STRING(ascii), start_file) && frame->f_lineno == start_line) { logging = 1; } Py_DECREF(ascii); @@ -853,7 +897,7 @@ CTracer_call(CTracer *self, PyObject *args, PyObject *kwds) for the C function. */ for (what = 0; what_names[what]; what++) { PyObject *ascii = MyText_AS_BYTES(what_str); - int should_break = !strcmp(MyText_AS_STRING(ascii), what_names[what]); + int should_break = !strcmp(MyBytes_AS_STRING(ascii), what_names[what]); Py_DECREF(ascii); if (should_break) { break; |