Skip to content

Commit 5a8ba25

Browse files
committed
cherrypick [b73516f7cfccbc9f] to 8.7 - closes [167e0635db]: solves leaks, valgrind test, etc
1 parent 6c80da1 commit 5a8ba25

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

generic/tclClock.c

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static struct tm * ThreadSafeLocalTime(const time_t *);
115115
static size_t TzsetIfNecessary(void);
116116
static void ClockDeleteCmdProc(void *);
117117
static Tcl_ObjCmdProc ClockSafeCatchCmd;
118+
static void ClockFinalize(void *);
118119
/*
119120
* Structure containing description of "native" clock commands to create.
120121
*/
@@ -180,6 +181,15 @@ TclClockInit(
180181
ClockClientData *data;
181182
int i;
182183

184+
static int initialized = 0; /* global clock engine initialized (in process) */
185+
/*
186+
* Register handler to finalize clock on exit.
187+
*/
188+
if (!initialized) {
189+
Tcl_CreateExitHandler(ClockFinalize, NULL);
190+
initialized = 1;
191+
}
192+
183193
/*
184194
* Safe interps get [::clock] as alias to a parent, so do not need their
185195
* own copies of the support routines.
@@ -352,12 +362,14 @@ ClockDeleteCmdProc(
352362
for (i = 0; i < MCLIT__END; ++i) {
353363
Tcl_DecrRefCount(data->mcLiterals[i]);
354364
}
365+
ckfree(data->mcLiterals);
355366
data->mcLiterals = NULL;
356367
}
357368
if (data->mcLitIdxs != NULL) {
358369
for (i = 0; i < MCLIT__END; ++i) {
359370
Tcl_DecrRefCount(data->mcLitIdxs[i]);
360371
}
372+
ckfree(data->mcLitIdxs);
361373
data->mcLitIdxs = NULL;
362374
}
363375

@@ -4638,20 +4650,25 @@ ClockSafeCatchCmd(
46384650
#endif
46394651
#define TZ_INIT_MARKER ((WCHAR *) INT2PTR(-1))
46404652

4653+
typedef struct ClockTzStatic {
4654+
WCHAR *was; /* Previous value of TZ. */
4655+
#if TCL_MAJOR_VERSION > 8
4656+
long long lastRefresh; /* Used for latency before next refresh. */
4657+
#else
4658+
long lastRefresh; /* Used for latency before next refresh. */
4659+
#endif
4660+
size_t epoch; /* Epoch, signals that TZ changed. */
4661+
size_t envEpoch; /* Last env epoch, for faster signaling,
4662+
* that TZ changed via TCL */
4663+
} ClockTzStatic;
4664+
static ClockTzStatic tz = { /* Global timezone info; protected by
4665+
* clockMutex.*/
4666+
TZ_INIT_MARKER, 0, 0, 0
4667+
};
4668+
46414669
static size_t
46424670
TzsetIfNecessary(void)
46434671
{
4644-
typedef struct ClockTzStatic {
4645-
WCHAR *was; /* Previous value of TZ. */
4646-
long lastRefresh; /* Used for latency before next refresh. */
4647-
size_t epoch; /* Epoch, signals that TZ changed. */
4648-
size_t envEpoch; /* Last env epoch, for faster signaling,
4649-
* that TZ changed via TCL */
4650-
} ClockTzStatic;
4651-
static ClockTzStatic tz = { /* Global timezone info; protected by
4652-
* clockMutex.*/
4653-
TZ_INIT_MARKER, 0, 0, 0
4654-
};
46554672
const WCHAR *tzNow; /* Current value of TZ. */
46564673
Tcl_Time now; /* Current time. */
46574674
size_t epoch; /* The tz.epoch that the TZ was read at. */
@@ -4701,6 +4718,19 @@ TzsetIfNecessary(void)
47014718
return epoch;
47024719
}
47034720

4721+
static void
4722+
ClockFinalize(
4723+
TCL_UNUSED(void *))
4724+
{
4725+
ClockFrmScnFinalize();
4726+
4727+
if (tz.was && tz.was != TZ_INIT_MARKER) {
4728+
ckfree(tz.was);
4729+
}
4730+
4731+
Tcl_MutexFinalize(&clockMutex);
4732+
}
4733+
47044734
/*
47054735
* Local Variables:
47064736
* mode: c

generic/tclClockFmt.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ static void ClockFmtObj_UpdateString(Tcl_Obj *objPtr);
2626
TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */
2727

2828
static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);
29-
static void ClockFrmScnFinalize(void *);
3029

3130
#ifndef TCL_CLOCK_FULL_COMPAT
3231
#define TCL_CLOCK_FULL_COMPAT 1
@@ -681,7 +680,7 @@ ClockFmtObj_FreeInternalRep(
681680
Tcl_Obj *objPtr)
682681
{
683682
ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
684-
if (fss != NULL) {
683+
if (fss != NULL && initialized) {
685684
Tcl_MutexLock(&ClockFmtMutex);
686685
/* decrement object reference count of format/scan storage */
687686
if (--fss->objRefCount <= 0) {
@@ -835,7 +834,6 @@ FindOrCreateFmtScnStorage(
835834
&ClockFmtScnStorageHashKeyType);
836835

837836
initialized = 1;
838-
Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
839837
}
840838

841839
/* get or create entry (and alocate storage) */
@@ -3560,10 +3558,12 @@ ClockFrmScnClearCaches(void)
35603558
Tcl_MutexUnlock(&ClockFmtMutex);
35613559
}
35623560

3563-
static void
3564-
ClockFrmScnFinalize(
3565-
TCL_UNUSED(void *))
3561+
void
3562+
ClockFrmScnFinalize()
35663563
{
3564+
if (!initialized) {
3565+
return;
3566+
}
35673567
Tcl_MutexLock(&ClockFmtMutex);
35683568
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
35693569
/* clear GC */
@@ -3572,8 +3572,8 @@ ClockFrmScnFinalize(
35723572
ClockFmtScnStorage_GC.count = 0;
35733573
#endif
35743574
if (initialized) {
3575-
Tcl_DeleteHashTable(&FmtScnHashTable);
35763575
initialized = 0;
3576+
Tcl_DeleteHashTable(&FmtScnHashTable);
35773577
}
35783578
Tcl_MutexUnlock(&ClockFmtMutex);
35793579
Tcl_MutexFinalize(&ClockFmtMutex);

generic/tclDate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,5 +560,6 @@ MODULE_SCOPE int ClockScan(DateInfo *info, Tcl_Obj *strObj,
560560
MODULE_SCOPE int ClockFormat(DateFormat *dateFmt,
561561
ClockFmtScnCmdArgs *opts);
562562
MODULE_SCOPE void ClockFrmScnClearCaches(void);
563+
MODULE_SCOPE void ClockFrmScnFinalize();
563564

564565
#endif /* _TCLCLOCK_H */

0 commit comments

Comments
 (0)