Skip to content

Commit 16dc2d4

Browse files
committed
closes [167e0635db]: solves leaks, valgrind test, etc
2 parents eee424d + 2a31c2e commit 16dc2d4

File tree

3 files changed

+45
-18
lines changed

3 files changed

+45
-18
lines changed

generic/tclClock.c

+37-11
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+
Tcl_Free(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+
Tcl_Free(data->mcLitIdxs);
361373
data->mcLitIdxs = NULL;
362374
}
363375

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

4653+
typedef struct ClockTzStatic {
4654+
WCHAR *was; /* Previous value of TZ. */
4655+
long long lastRefresh; /* Used for latency before next refresh. */
4656+
size_t epoch; /* Epoch, signals that TZ changed. */
4657+
size_t envEpoch; /* Last env epoch, for faster signaling,
4658+
* that TZ changed via TCL */
4659+
} ClockTzStatic;
4660+
static ClockTzStatic tz = { /* Global timezone info; protected by
4661+
* clockMutex.*/
4662+
TZ_INIT_MARKER, 0, 0, 0
4663+
};
4664+
46414665
static size_t
46424666
TzsetIfNecessary(void)
46434667
{
4644-
typedef struct ClockTzStatic {
4645-
WCHAR *was; /* Previous value of TZ. */
4646-
long 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-
};
46554668
const WCHAR *tzNow; /* Current value of TZ. */
46564669
Tcl_Time now; /* Current time. */
46574670
size_t epoch; /* The tz.epoch that the TZ was read at. */
@@ -4700,6 +4713,19 @@ TzsetIfNecessary(void)
47004713
return epoch;
47014714
}
47024715

4716+
static void
4717+
ClockFinalize(
4718+
TCL_UNUSED(void *))
4719+
{
4720+
ClockFrmScnFinalize();
4721+
4722+
if (tz.was && tz.was != TZ_INIT_MARKER) {
4723+
Tcl_Free(tz.was);
4724+
}
4725+
4726+
Tcl_MutexFinalize(&clockMutex);
4727+
}
4728+
47034729
/*
47044730
* Local Variables:
47054731
* mode: c

generic/tclClockFmt.c

+7-7
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
@@ -682,7 +681,7 @@ ClockFmtObj_FreeInternalRep(
682681
Tcl_Obj *objPtr)
683682
{
684683
ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr);
685-
if (fss != NULL) {
684+
if (fss != NULL && initialized) {
686685
Tcl_MutexLock(&ClockFmtMutex);
687686
/* decrement object reference count of format/scan storage */
688687
if (--fss->objRefCount <= 0) {
@@ -836,7 +835,6 @@ FindOrCreateFmtScnStorage(
836835
&ClockFmtScnStorageHashKeyType);
837836

838837
initialized = 1;
839-
Tcl_CreateExitHandler(ClockFrmScnFinalize, NULL);
840838
}
841839

842840
/* get or create entry (and alocate storage) */
@@ -3561,10 +3559,12 @@ ClockFrmScnClearCaches(void)
35613559
Tcl_MutexUnlock(&ClockFmtMutex);
35623560
}
35633561

3564-
static void
3565-
ClockFrmScnFinalize(
3566-
TCL_UNUSED(void *))
3562+
void
3563+
ClockFrmScnFinalize()
35673564
{
3565+
if (!initialized) {
3566+
return;
3567+
}
35683568
Tcl_MutexLock(&ClockFmtMutex);
35693569
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
35703570
/* clear GC */
@@ -3573,8 +3573,8 @@ ClockFrmScnFinalize(
35733573
ClockFmtScnStorage_GC.count = 0;
35743574
#endif
35753575
if (initialized) {
3576-
Tcl_DeleteHashTable(&FmtScnHashTable);
35773576
initialized = 0;
3577+
Tcl_DeleteHashTable(&FmtScnHashTable);
35783578
}
35793579
Tcl_MutexUnlock(&ClockFmtMutex);
35803580
Tcl_MutexFinalize(&ClockFmtMutex);

generic/tclDate.h

+1
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)