From be2711831fcc4b2282764665de79d0d3c50754e2 Mon Sep 17 00:00:00 2001 From: sebres Date: Sun, 14 Apr 2024 16:54:34 +0200 Subject: [PATCH] code review, close few mem-leaks (following tcl-core [167e0635db79f05d]) --- generic/tclClock.c | 28 +++++++++++++++++++++++++--- generic/tclClockFmt.c | 15 +++++++-------- generic/tclDate.h | 1 + 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 141ad58..980ff1b 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -146,6 +146,7 @@ static void ClockDeleteCmdProc(ClientData); static int ClockSafeCatchCmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); +static void ClockFinalize(void *); /* * Structure containing description of "native" clock commands to create. */ @@ -212,6 +213,15 @@ TclClockInit( ClockClientData *data; int i; + static int initialized = 0; /* global clock engine initialized (in process) */ + /* + * Register handler to finalize clock on exit. + */ + if (!initialized) { + Tcl_CreateExitHandler(ClockFinalize, NULL); + initialized = 1; + } + /* * Safe interps get [::clock] as alias to a master, so do not need their * own copies of the support routines. @@ -378,12 +388,14 @@ ClockDeleteCmdProc( for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLiterals[i]); } + ckfree(data->mcLiterals); data->mcLiterals = NULL; } if (data->mcLitIdxs != NULL) { for (i = 0; i < MCLIT__END; ++i) { Tcl_DecrRefCount(data->mcLitIdxs[i]); } + ckfree(data->mcLitIdxs); data->mcLitIdxs = NULL; } @@ -4659,12 +4671,11 @@ ClockSafeCatchCmd( * *---------------------------------------------------------------------- */ - +static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by + * clockMutex. */ static size_t TzsetIfNecessary(void) { - static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by - * clockMutex. */ static long tzLastRefresh = 0; /* Used for latency before next refresh */ static size_t tzWasEpoch = 0; /* Epoch, signals that TZ changed */ static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling, @@ -4711,6 +4722,17 @@ TzsetIfNecessary(void) return tzWasEpoch; } +static void +ClockFinalize( + ClientData clientData) +{ + ClockFrmScnFinalize(); + + if (tzWas && tzWas != INT2PTR(-1)) { + ckfree(tzWas); + } +} + /* * Local Variables: * mode: c diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 99a6c70..e420fba 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -32,8 +32,6 @@ TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */ static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss); -static void ClockFrmScnFinalize(ClientData clientData); - /* * Clock scan and format facilities. */ @@ -642,7 +640,7 @@ ClockFmtObj_FreeInternalRep(objPtr) Tcl_Obj *objPtr; { ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr); - if (fss != NULL) { + if (fss != NULL && initialized) { Tcl_MutexLock(&ClockFmtMutex); /* decrement object reference count of format/scan storage */ if (--fss->objRefCount <= 0) { @@ -796,7 +794,6 @@ FindOrCreateFmtScnStorage( &ClockFmtScnStorageHashKeyType); initialized = 1; - Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL); } /* get or create entry (and alocate storage) */ @@ -3443,10 +3440,12 @@ ClockFrmScnClearCaches(void) Tcl_MutexUnlock(&ClockFmtMutex); } -static void -ClockFrmScnFinalize( - ClientData clientData) /* Not used. */ +void +ClockFrmScnFinalize() { + if (!initialized) { + return; + } Tcl_MutexLock(&ClockFmtMutex); #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 /* clear GC */ @@ -3455,8 +3454,8 @@ ClockFrmScnFinalize( ClockFmtScnStorage_GC.count = 0; #endif if (initialized) { - Tcl_DeleteHashTable(&FmtScnHashTable); initialized = 0; + Tcl_DeleteHashTable(&FmtScnHashTable); } Tcl_MutexUnlock(&ClockFmtMutex); Tcl_MutexFinalize(&ClockFmtMutex); diff --git a/generic/tclDate.h b/generic/tclDate.h index f4ae511..a77ea95 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -606,5 +606,6 @@ MODULE_SCOPE int ClockFormat(register DateFormat *dateFmt, ClockFmtScnCmdArgs *opts); MODULE_SCOPE void ClockFrmScnClearCaches(void); +MODULE_SCOPE void ClockFrmScnFinalize(); #endif /* _TCLCLOCK_H */