Ticket UUID: | 9969cf8ca6fa749fa0952186957fd3ac110be5b3 | |||
Title: | memleak in execute-10.3 | |||
Type: | Bug | Version: | trunk | |
Submitter: | dgp | Created on: | 2014-07-11 21:27:07 | |
Subsystem: | 47. Bytecode Compiler | Assigned To: | dgp | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Open | Last Modified: | 2014-07-21 14:34:59 | |
Resolution: | None | Closed By: | nobody | |
Closed on: | ||||
Description: |
==4219== 157 (96 direct, 61 indirect) bytes in 2 blocks are definitely lost in loss record 5 of 7 ==4219== at 0x4A0610C: malloc (vg_replace_malloc.c:195) ==4219== by 0x5D14E2: TclpAlloc (tclAlloc.c:699) ==4219== by 0x43D1AE: Tcl_Alloc (tclCkalloc.c:1059) ==4219== by 0x571252: Tcl_NewStringObj (tclStringObj.c:340) ==4219== by 0x516C69: TclGetSourceFromFrame (tclExecute.c:9735) ==4219== by 0x4306B8: EvalObjvCore (tclBasic.c:4262) ==4219== by 0x4309D8: TclNRRunCallbacks (tclBasic.c:4390) ==4219== by 0x43027D: Tcl_EvalObjv (tclBasic.c:4121) | |||
User Comments: |
dgp added on 2014-07-17 04:27:42:
Whoa. This is either a stroke of dumb luck, or a consequence of well-crafter Sofer design. I found where the ->rewind bails out on coroutine deletion and saw that teardown of trace data in frames comes right after. The leak appears to be a consequence of just this small misordering of code. Fix committed. The interaction of execution traces and [yield]ing commands still holds some mysteries I think, but I'll open another ticket for that, and keep this one open until I do. Leak plugged. And there was much rejoicing... dgp added on 2014-07-17 03:51:45: Simplest demo I can manage of how things are functioning now: % trace add execution yield {enter leave} {apply {{cmd args} {puts $args}}} % coroutine coro yield enter % coro 0 {} leave I can convince myself that's correct. dgp added on 2014-07-17 03:41:34: Oh boy. Test execute-10.3 came in to test that a crashing scenario in Ticket 3072640 stopped crashing. The leak here appears to be exposing that although things are not crashing, they don't seem to be working properly either. The issue appears to be how to handle execution leave traces for the [yield] command or for other commands like [for] or [while] that can end up yielding due to [yield] in their bodies. When these commands yield, in some sense they are blocking, they are still in progress, and we may sometime later return to them and let them complete and leave at that time. So their leave traces do not fire *yet*. Execution trace implementation creates things for enter traces and destroys them after leave traces. That's why we see a leak. Those commands that never leave, never clean up their execution trace housekeeping. What's strange is that after the [yield], the execution trace appears to still be in effect, now tracing a whole other body of code. In the test execute-8.3, a bit of debug printing will reveal that the command ::t {trace remove execution ::generate enterstep ::t} enterstep is invoked, even though I would not normally think of the [trace remove] being part of [::generate]. The other thing that appears missing is that I would think that when it becomes clear the coro will never be resumed (with [rename coro {}], then we ought to be cleaning up the abandoned trace housekeeping, and that's not happening (thus the leak)). My head hurts. |