File: | coverage/tracer.c |
Function: | Tracer_trace |
Error: | ob_refcnt of '*tracename' is 1 too high |
254 static int
255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused)
256 {
257 int ret = RET_OK;
258 PyObject * filename = NULL;
259 PyObject * tracename = NULL;
260
261 #if WHAT_LOG
262 if (what <= sizeof(what_sym)/sizeof(const char *)) {
263 printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno);
264 }
265 #endif
266
267 #if TRACE_LOG
268 if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) {
269 logging = 1;
270 }
271 #endif
272
273 /* See below for details on missing-return detection. */
274 if (self->last_exc_back) {
1 when treating unknown struct PyFrameObject * from coverage/tracer.c:274 as non-NULL
2 taking True path
275 if (frame == self->last_exc_back) {
3 when taking True path
276 /* Looks like someone forgot to send a return event. We'll clear
277 the exception state and do the RETURN code here. Notice that the
278 frame we have in hand here is not the correct frame for the RETURN,
279 that frame is gone. Our handling for RETURN doesn't need the
280 actual frame, but we do log it, so that will look a little off if
281 you're looking at the detailed log.
282
283 If someday we need to examine the frame when doing RETURN, then
284 we'll need to keep more of the missed frame's state.
285 */
286 STATS( self->stats.missed_returns++; )
287 if (self->depth >= 0) {
4 when considering range: -0x80000000 <= value <= -1
5 taking False path
288 if (self->tracing_arcs && self->cur_file_data) {
289 if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) {
290 return RET_ERROR;
291 }
292 }
293 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn");
294 self->cur_file_data = self->data_stack[self->depth].file_data;
295 self->last_line = self->data_stack[self->depth].last_line;
296 self->depth--;
297 }
298 }
299 self->last_exc_back = NULL;
300 }
301
302
303 switch (what) {
6 when following case 0
304 case PyTrace_CALL: /* 0 */
305 STATS( self->stats.calls++; )
306 /* Grow the stack. */
307 self->depth++;
308 if (self->depth >= self->data_stack_alloc) {
7 when taking True path
309 STATS( self->stats.stack_reallocs++; )
310 /* We've outgrown our data_stack array: make it bigger. */
311 int bigger = self->data_stack_alloc + STACK_DELTA;
312 DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry));
313 if (bigger_data_stack == NULL) {
8 when treating unknown void * from coverage/tracer.c:312 as non-NULL
9 taking False path
314 STATS( self->stats.errors++; )
315 PyErr_NoMemory();
316 self->depth--;
317 return RET_ERROR;
318 }
319 self->data_stack = bigger_data_stack;
320 self->data_stack_alloc = bigger;
321 }
322
323 /* Push the current state on the stack. */
324 self->data_stack[self->depth].file_data = self->cur_file_data;
10 when treating unknown struct DataStackEntry * from coverage/tracer.c:324 as non-NULL
325 self->data_stack[self->depth].last_line = self->last_line;
11 when treating unknown struct DataStackEntry * from coverage/tracer.c:325 as non-NULL
326
327 /* Check if we should trace this line. */
328 filename = frame->f_code->co_filename;
12 when treating unknown struct PyCodeObject * from coverage/tracer.c:328 as non-NULL
329 tracename = PyDict_GetItem(self->should_trace_cache, filename);
13 when treating unknown struct PyObject * from coverage/tracer.c:329 as non-NULL
14 when treating unknown struct PyObject * from coverage/tracer.c:328 as non-NULL
15 when PyDict_GetItem does not find item
330 if (tracename == NULL) {
16 taking True path
331 STATS( self->stats.new_files++; )
332 /* We've never considered this file before. */
333 /* Ask should_trace about it. */
334 PyObject * args = Py_BuildValue("(OO)", filename, frame);
17 when Py_BuildValue() succeeds
335 tracename = PyObject_Call(self->should_trace, args, NULL);
18 when treating unknown struct PyObject * from coverage/tracer.c:335 as non-NULL
19 when PyObject_Call() succeeds
ob_refcnt is now refs: 1 + N where N >= 0
336 Py_DECREF(args);
20 when taking True path
337 if (tracename == NULL) {
21 taking False path
338 /* An error occurred inside should_trace. */
339 STATS( self->stats.errors++; )
340 return RET_ERROR;
341 }
342 if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) {
22 when treating unknown struct PyObject * from coverage/tracer.c:342 as non-NULL
23 when PyDict_SetItem() succeeds
ob_refcnt is now refs: 1 + N where N >= 1
24 taking False path
343 STATS( self->stats.errors++; )
344 return RET_ERROR;
345 }
346 }
347 else {
348 Py_INCREF(tracename);
349 }
350
351 /* If tracename is a string, then we're supposed to trace. */
352 if (MyText_Check(tracename)) {
25 when considering range: 1 <= value <= 0x8000000
26 taking True path
353 PyObject * file_data = PyDict_GetItem(self->data, tracename);
27 when treating unknown struct PyObject * from coverage/tracer.c:353 as non-NULL
28 when PyDict_GetItem does not find item
354 if (file_data == NULL) {
29 taking True path
355 file_data = PyDict_New();
30 when PyDict_New() succeeds
356 if (file_data == NULL) {
31 taking False path
357 STATS( self->stats.errors++; )
358 return RET_ERROR;
359 }
360 ret = PyDict_SetItem(self->data, tracename, file_data);
32 when treating unknown struct PyObject * from coverage/tracer.c:360 as non-NULL
33 when PyDict_SetItem() fails
361 Py_DECREF(file_data);
34 when taking True path
362 if (ret < 0) {
35 taking True path
363 STATS( self->stats.errors++; )
364 return RET_ERROR;
365 }
366 }
367 self->cur_file_data = file_data;
368 /* Make the frame right in case settrace(gettrace()) happens. */
369 Py_INCREF(self);
370 frame->f_trace = (PyObject*)self;
371 SHOWLOG(self->depth, frame->f_lineno, filename, "traced");
372 }
373 else {
374 self->cur_file_data = NULL;
375 SHOWLOG(self->depth, frame->f_lineno, filename, "skipped");
376 }
377
378 Py_DECREF(tracename);
379
380 self->last_line = -1;
381 break;
382
383 case PyTrace_RETURN: /* 3 */
384 STATS( self->stats.returns++; )
385 /* A near-copy of this code is above in the missing-return handler. */
386 if (self->depth >= 0) {
387 if (self->tracing_arcs && self->cur_file_data) {
388 int first = frame->f_code->co_firstlineno;
389 if (Tracer_record_pair(self, self->last_line, -first) < 0) {
390 return RET_ERROR;
391 }
392 }
393
394 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return");
395 self->cur_file_data = self->data_stack[self->depth].file_data;
396 self->last_line = self->data_stack[self->depth].last_line;
397 self->depth--;
398 }
399 break;
400
401 case PyTrace_LINE: /* 2 */
402 STATS( self->stats.lines++; )
403 if (self->depth >= 0) {
404 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line");
405 if (self->cur_file_data) {
406 /* We're tracing in this frame: record something. */
407 if (self->tracing_arcs) {
408 /* Tracing arcs: key is (last_line,this_line). */
409 if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) {
410 return RET_ERROR;
411 }
412 }
413 else {
414 /* Tracing lines: key is simply this_line. */
415 PyObject * this_line = MyInt_FromLong(frame->f_lineno);
416 if (this_line == NULL) {
417 STATS( self->stats.errors++; )
418 return RET_ERROR;
419 }
420 ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None);
421 Py_DECREF(this_line);
422 if (ret < 0) {
423 STATS( self->stats.errors++; )
424 return RET_ERROR;
425 }
426 }
427 }
428 self->last_line = frame->f_lineno;
429 }
430 break;
431
432 case PyTrace_EXCEPTION:
433 /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event
434 without a return event. To detect that, we'll keep a copy of the
435 parent frame for an exception event. If the next event is in that
436 frame, then we must have returned without a return event. We can
437 synthesize the missing event then.
438
439 Python itself fixed this problem in 2.4. Pyexpat still has the bug.
440 I've reported the problem with pyexpat as http://bugs.python.org/issue6359 .
441 If it gets fixed, this code should still work properly. Maybe some day
442 the bug will be fixed everywhere coverage.py is supported, and we can
443 remove this missing-return detection.
444
445 More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html
446 */
447 STATS( self->stats.exceptions++; )
448 self->last_exc_back = frame->f_back;
449 self->last_exc_firstlineno = frame->f_code->co_firstlineno;
450 break;
451
452 default:
453 STATS( self->stats.others++; )
454 break;
455 }
456
457 return RET_OK;
458 }
ob_refcnt of '*tracename' is 1 too high
File: | coverage/tracer.c |
Function: | Tracer_trace |
Error: | ob_refcnt of '*self' is 1 too high |
254 static int
255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused)
256 {
257 int ret = RET_OK;
258 PyObject * filename = NULL;
259 PyObject * tracename = NULL;
260
261 #if WHAT_LOG
262 if (what <= sizeof(what_sym)/sizeof(const char *)) {
263 printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno);
264 }
265 #endif
266
267 #if TRACE_LOG
268 if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) {
269 logging = 1;
270 }
271 #endif
272
273 /* See below for details on missing-return detection. */
274 if (self->last_exc_back) {
1 when treating unknown struct PyFrameObject * from coverage/tracer.c:274 as non-NULL
2 taking True path
275 if (frame == self->last_exc_back) {
3 when taking True path
276 /* Looks like someone forgot to send a return event. We'll clear
277 the exception state and do the RETURN code here. Notice that the
278 frame we have in hand here is not the correct frame for the RETURN,
279 that frame is gone. Our handling for RETURN doesn't need the
280 actual frame, but we do log it, so that will look a little off if
281 you're looking at the detailed log.
282
283 If someday we need to examine the frame when doing RETURN, then
284 we'll need to keep more of the missed frame's state.
285 */
286 STATS( self->stats.missed_returns++; )
287 if (self->depth >= 0) {
4 when considering range: -0x80000000 <= value <= -1
5 taking False path
288 if (self->tracing_arcs && self->cur_file_data) {
289 if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) {
290 return RET_ERROR;
291 }
292 }
293 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn");
294 self->cur_file_data = self->data_stack[self->depth].file_data;
295 self->last_line = self->data_stack[self->depth].last_line;
296 self->depth--;
297 }
298 }
299 self->last_exc_back = NULL;
300 }
301
302
303 switch (what) {
6 when following case 0
304 case PyTrace_CALL: /* 0 */
305 STATS( self->stats.calls++; )
306 /* Grow the stack. */
307 self->depth++;
308 if (self->depth >= self->data_stack_alloc) {
7 when taking True path
309 STATS( self->stats.stack_reallocs++; )
310 /* We've outgrown our data_stack array: make it bigger. */
311 int bigger = self->data_stack_alloc + STACK_DELTA;
312 DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry));
313 if (bigger_data_stack == NULL) {
8 when treating unknown void * from coverage/tracer.c:312 as non-NULL
9 taking False path
314 STATS( self->stats.errors++; )
315 PyErr_NoMemory();
316 self->depth--;
317 return RET_ERROR;
318 }
319 self->data_stack = bigger_data_stack;
320 self->data_stack_alloc = bigger;
321 }
322
323 /* Push the current state on the stack. */
324 self->data_stack[self->depth].file_data = self->cur_file_data;
10 when treating unknown struct DataStackEntry * from coverage/tracer.c:324 as non-NULL
325 self->data_stack[self->depth].last_line = self->last_line;
11 when treating unknown struct DataStackEntry * from coverage/tracer.c:325 as non-NULL
326
327 /* Check if we should trace this line. */
328 filename = frame->f_code->co_filename;
12 when treating unknown struct PyCodeObject * from coverage/tracer.c:328 as non-NULL
329 tracename = PyDict_GetItem(self->should_trace_cache, filename);
13 when treating unknown struct PyObject * from coverage/tracer.c:329 as non-NULL
14 when treating unknown struct PyObject * from coverage/tracer.c:328 as non-NULL
15 when PyDict_GetItem does not find item
330 if (tracename == NULL) {
16 taking True path
331 STATS( self->stats.new_files++; )
332 /* We've never considered this file before. */
333 /* Ask should_trace about it. */
334 PyObject * args = Py_BuildValue("(OO)", filename, frame);
17 when Py_BuildValue() succeeds
335 tracename = PyObject_Call(self->should_trace, args, NULL);
18 when treating unknown struct PyObject * from coverage/tracer.c:335 as non-NULL
19 when PyObject_Call() succeeds
336 Py_DECREF(args);
20 when taking True path
337 if (tracename == NULL) {
21 taking False path
338 /* An error occurred inside should_trace. */
339 STATS( self->stats.errors++; )
340 return RET_ERROR;
341 }
342 if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) {
22 when treating unknown struct PyObject * from coverage/tracer.c:342 as non-NULL
23 when PyDict_SetItem() succeeds
24 taking False path
343 STATS( self->stats.errors++; )
344 return RET_ERROR;
345 }
346 }
347 else {
348 Py_INCREF(tracename);
349 }
350
351 /* If tracename is a string, then we're supposed to trace. */
352 if (MyText_Check(tracename)) {
25 when considering range: 1 <= value <= 0x8000000
26 taking True path
353 PyObject * file_data = PyDict_GetItem(self->data, tracename);
27 when treating unknown struct PyObject * from coverage/tracer.c:353 as non-NULL
28 when PyDict_GetItem does not find item
354 if (file_data == NULL) {
29 taking True path
355 file_data = PyDict_New();
30 when PyDict_New() succeeds
356 if (file_data == NULL) {
31 taking False path
357 STATS( self->stats.errors++; )
358 return RET_ERROR;
359 }
360 ret = PyDict_SetItem(self->data, tracename, file_data);
32 when treating unknown struct PyObject * from coverage/tracer.c:360 as non-NULL
33 when PyDict_SetItem() succeeds
361 Py_DECREF(file_data);
34 taking True path
362 if (ret < 0) {
35 taking False path
363 STATS( self->stats.errors++; )
364 return RET_ERROR;
365 }
366 }
367 self->cur_file_data = file_data;
368 /* Make the frame right in case settrace(gettrace()) happens. */
369 Py_INCREF(self);
36 ob_refcnt is now refs: 1 + N where N >= 1
370 frame->f_trace = (PyObject*)self;
371 SHOWLOG(self->depth, frame->f_lineno, filename, "traced");
372 }
373 else {
374 self->cur_file_data = NULL;
375 SHOWLOG(self->depth, frame->f_lineno, filename, "skipped");
376 }
377
378 Py_DECREF(tracename);
37 taking True path
379
380 self->last_line = -1;
381 break;
382
383 case PyTrace_RETURN: /* 3 */
384 STATS( self->stats.returns++; )
385 /* A near-copy of this code is above in the missing-return handler. */
386 if (self->depth >= 0) {
387 if (self->tracing_arcs && self->cur_file_data) {
388 int first = frame->f_code->co_firstlineno;
389 if (Tracer_record_pair(self, self->last_line, -first) < 0) {
390 return RET_ERROR;
391 }
392 }
393
394 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return");
395 self->cur_file_data = self->data_stack[self->depth].file_data;
396 self->last_line = self->data_stack[self->depth].last_line;
397 self->depth--;
398 }
399 break;
400
401 case PyTrace_LINE: /* 2 */
402 STATS( self->stats.lines++; )
403 if (self->depth >= 0) {
404 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line");
405 if (self->cur_file_data) {
406 /* We're tracing in this frame: record something. */
407 if (self->tracing_arcs) {
408 /* Tracing arcs: key is (last_line,this_line). */
409 if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) {
410 return RET_ERROR;
411 }
412 }
413 else {
414 /* Tracing lines: key is simply this_line. */
415 PyObject * this_line = MyInt_FromLong(frame->f_lineno);
416 if (this_line == NULL) {
417 STATS( self->stats.errors++; )
418 return RET_ERROR;
419 }
420 ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None);
421 Py_DECREF(this_line);
422 if (ret < 0) {
423 STATS( self->stats.errors++; )
424 return RET_ERROR;
425 }
426 }
427 }
428 self->last_line = frame->f_lineno;
429 }
430 break;
431
432 case PyTrace_EXCEPTION:
433 /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event
434 without a return event. To detect that, we'll keep a copy of the
435 parent frame for an exception event. If the next event is in that
436 frame, then we must have returned without a return event. We can
437 synthesize the missing event then.
438
439 Python itself fixed this problem in 2.4. Pyexpat still has the bug.
440 I've reported the problem with pyexpat as http://bugs.python.org/issue6359 .
441 If it gets fixed, this code should still work properly. Maybe some day
442 the bug will be fixed everywhere coverage.py is supported, and we can
443 remove this missing-return detection.
444
445 More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html
446 */
447 STATS( self->stats.exceptions++; )
448 self->last_exc_back = frame->f_back;
449 self->last_exc_firstlineno = frame->f_code->co_firstlineno;
450 break;
451
452 default:
453 STATS( self->stats.others++; )
454 break;
455 }
456
457 return RET_OK;
458 }
ob_refcnt of '*self' is 1 too high