diff options
| author | apnadkarni <apnmbx-wits@yahoo.com> | 2024-05-24 16:05:19 (GMT) |
|---|---|---|
| committer | apnadkarni <apnmbx-wits@yahoo.com> | 2024-05-24 16:05:19 (GMT) |
| commit | b7eeffcdef4802086b4f43db1619b2784d74aa79 (patch) | |
| tree | 0e5d90abdf8a9e69a0fc4383d8ceac9d115a02c4 /generic/tclIORChan.c | |
| parent | 14145609e7b52c939ce5bc328b87b8ab02c7a431 (diff) | |
| parent | b230de2a4d3e8748a542c21d0dfde9e357ac0b0a (diff) | |
| download | tcl-b7eeffcdef4802086b4f43db1619b2784d74aa79.zip tcl-b7eeffcdef4802086b4f43db1619b2784d74aa79.tar.gz tcl-b7eeffcdef4802086b4f43db1619b2784d74aa79.tar.bz2 | |
Merge trunk
Diffstat (limited to 'generic/tclIORChan.c')
| -rw-r--r-- | generic/tclIORChan.c | 82 |
1 files changed, 42 insertions, 40 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 5acd950..e8a243b 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -60,27 +60,27 @@ static int ReflectTruncate(void *clientData, */ static const Tcl_ChannelType tclRChannelType = { - "tclrchannel", /* Type name. */ + "tclrchannel", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - NULL, /* Close channel, clean instance data */ - ReflectInput, /* Handle read request */ - ReflectOutput, /* Handle write request */ + NULL, /* Old close API */ + ReflectInput, /* Handle read request */ + ReflectOutput, /* Handle write request */ NULL, - ReflectSetOption, /* Set options. NULL'able */ - ReflectGetOption, /* Get options. NULL'able */ - ReflectWatch, /* Initialize notifier */ - NULL, /* Get OS handle from the channel. NULL'able */ - ReflectClose, /* No close2 support. NULL'able */ - ReflectBlock, /* Set blocking/nonblocking. NULL'able */ - NULL, /* Flush channel. Not used by core. NULL'able */ - NULL, /* Handle events. NULL'able */ - ReflectSeekWide, /* Move access point (64 bit). NULL'able */ + ReflectSetOption, /* Set options. */ + ReflectGetOption, /* Get options. */ + ReflectWatch, /* Initialize notifier */ + NULL, /* Get OS handle from the channel. */ + ReflectClose, /* Close channel. Clean instance data */ + ReflectBlock, /* Set blocking/nonblocking. */ + NULL, /* Flush channel. */ + NULL, /* Handle events. */ + ReflectSeekWide, /* Move access point (64 bit). */ #if TCL_THREADS - ReflectThread, /* thread action, tracking owner */ + ReflectThread, /* thread action, tracking owner */ #else - NULL, /* thread action */ + NULL, /* thread action */ #endif - ReflectTruncate /* Truncate. NULL'able */ + ReflectTruncate /* Truncate. */ }; /* @@ -94,11 +94,10 @@ typedef struct { * Tcl level part of the channel. NULL here * signals the channel is dead because the * interpreter/thread containing its Tcl - * command is gone. - */ + * command is gone. */ #if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ - Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ + Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif Tcl_Obj *cmd; /* Callback command prefix */ Tcl_Obj *methods; /* Methods to append to command prefix */ @@ -255,7 +254,7 @@ typedef struct { struct ForwardParamInput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* O: Where to store the read bytes */ - Tcl_Size toRead; /* I: #bytes to read, + Tcl_Size toRead; /* I: #bytes to read, * O: #bytes actually read */ }; struct ForwardParamOutput { @@ -502,7 +501,7 @@ TclChanCreateObjCmd( Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Channel chan; /* Token for the new channel */ Tcl_Obj *modeObj; /* mode in obj form for method call */ - Tcl_Size listc; /* Result of 'initialize', and of */ + Tcl_Size listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ @@ -2262,23 +2261,37 @@ NextHandle(void) return resObj; } -static void -FreeReflectedChannel( - void *blockPtr) +static inline void +CleanRefChannelInstance( + ReflectedChannel *rcPtr) { - ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; - Channel *chanPtr = (Channel *) rcPtr->chan; - - TclChannelRelease((Tcl_Channel)chanPtr); if (rcPtr->name) { + /* + * Reset obj-type (channel is deleted or dead anyway) to avoid leakage + * by cyclic references (see bug [79474c58800cdf94]). + */ + TclFreeInternalRep(rcPtr->name); Tcl_DecrRefCount(rcPtr->name); + rcPtr->name = NULL; } if (rcPtr->methods) { Tcl_DecrRefCount(rcPtr->methods); + rcPtr->methods = NULL; } if (rcPtr->cmd) { Tcl_DecrRefCount(rcPtr->cmd); + rcPtr->cmd = NULL; } +} +static void +FreeReflectedChannel( + void *blockPtr) +{ + ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; + Channel *chanPtr = (Channel *) rcPtr->chan; + + TclChannelRelease((Tcl_Channel)chanPtr); + CleanRefChannelInstance(rcPtr); Tcl_Free(rcPtr); } @@ -2548,18 +2561,7 @@ MarkDead( if (rcPtr->dead) { return; } - if (rcPtr->name) { - Tcl_DecrRefCount(rcPtr->name); - rcPtr->name = NULL; - } - if (rcPtr->methods) { - Tcl_DecrRefCount(rcPtr->methods); - rcPtr->methods = NULL; - } - if (rcPtr->cmd) { - Tcl_DecrRefCount(rcPtr->cmd); - rcPtr->cmd = NULL; - } + CleanRefChannelInstance(rcPtr); rcPtr->dead = 1; } |
