diff options
| author | dgp@users.sourceforge.net <dgp> | 2014-05-09 13:33:27 (GMT) |
|---|---|---|
| committer | dgp@users.sourceforge.net <dgp> | 2014-05-09 13:33:27 (GMT) |
| commit | f52fdf223783445a0d88f6f536079fc1a2737fde (patch) | |
| tree | e100a9dd09c5eefd4e813b1d2574ed68490f5f7d | |
| parent | c22407144a446db6ac7e054d98d55704ae5b5e3f (diff) | |
| parent | b71ff1c6925646c5046fb9bf4a5b0883b97d7d66 (diff) | |
| download | tcl-f52fdf223783445a0d88f6f536079fc1a2737fde.zip tcl-f52fdf223783445a0d88f6f536079fc1a2737fde.tar.gz tcl-f52fdf223783445a0d88f6f536079fc1a2737fde.tar.bz2 | |
Test iocmd-32.1 is not "impossible" but after writing it properly it does segfault trying to use a deleted interp. Fixed.
| -rw-r--r-- | generic/tclIORChan.c | 12 | ||||
| -rw-r--r-- | tests/ioCmd.test | 9 |
2 files changed, 15 insertions, 6 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 0b462c4..6a43441 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -450,8 +450,8 @@ static const char *msg_write_nothing = "{write wrote nothing}"; static const char *msg_seek_beforestart = "{Tried to seek before origin}"; #ifdef TCL_THREADS static const char *msg_send_originlost = "{Channel thread lost}"; -static const char *msg_send_dstlost = "{Owner lost}"; #endif /* TCL_THREADS */ +static const char *msg_send_dstlost = "{Owner lost}"; static const char *msg_dstlost = "-code 1 -level 0 -errorcode NONE -errorinfo {} -errorline 1 {Owner lost}"; /* @@ -1397,6 +1397,7 @@ ReflectOutput( /* ASSERT: rcPtr->mode & TCL_WRITABLE */ Tcl_Preserve(rcPtr); + Tcl_Preserve(rcPtr->interp); bufObj = Tcl_NewByteArrayObj((unsigned char *) buf, toWrite); Tcl_IncrRefCount(bufObj); @@ -1413,6 +1414,14 @@ ReflectOutput( goto invalid; } + if (Tcl_InterpDeleted(rcPtr->interp)) { + /* + * The interp was destroyed during InvokeTclMethod(). + */ + + SetChannelErrorStr(rcPtr->chan, msg_send_dstlost); + goto invalid; + } if (Tcl_GetIntFromObj(rcPtr->interp, resObj, &written) != TCL_OK) { Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp)); goto invalid; @@ -1442,6 +1451,7 @@ ReflectOutput( stop: Tcl_DecrRefCount(bufObj); Tcl_DecrRefCount(resObj); /* Remove reference held from invoke */ + Tcl_Release(rcPtr->interp); Tcl_Release(rcPtr); return written; invalid: diff --git a/tests/ioCmd.test b/tests/ioCmd.test index ebc9cc7..ff93719 100644 --- a/tests/ioCmd.test +++ b/tests/ioCmd.test @@ -2076,13 +2076,13 @@ test iocmd-32.1 {origin interpreter of moved channel destroyed during access} -m proc foo {args} { oninit; onfinal; track; # destroy interpreter during channel access - # Actually not possible for an interp to destroy itself. - interp delete {} - return} + suicide + } set chan [chan create {r w} foo] fconfigure $chan -buffering none set chan }] + interp alias $ida suicide {} interp delete $ida # Move channel to 2nd thread. interp eval $ida [list testchannel cut $chan] @@ -2100,8 +2100,7 @@ test iocmd-32.1 {origin interpreter of moved channel destroyed during access} -m set res }] set res -} -constraints {testchannel impossible} \ - -result {Owner lost} +} -constraints {testchannel} -result {Owner lost} test iocmd-32.2 {delete interp of reflected chan} { # Bug 3034840 |
