summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-09-29 16:39:33 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-09-29 16:39:33 (GMT)
commit5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c (patch)
treef11cafbcf833276f3aa894797720253e5fd979c5 /generic
parentc0f753dfae6d69344ff84eb052f91971f304e652 (diff)
downloadtcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.zip
tcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.tar.gz
tcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.tar.bz2
Refactor zipfs finalization
Diffstat (limited to 'generic')
-rw-r--r--generic/tclIO.c3
-rw-r--r--generic/tclInt.h5
-rw-r--r--generic/tclZipfs.c114
3 files changed, 91 insertions, 31 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 1527dc0..2e25d2d 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -706,8 +706,9 @@ TclFinalizeIOSubsystem(void)
TclpFinalizeSockets();
TclpFinalizePipes();
+ TclZipfsFinalize();
}
-
+
/*
*----------------------------------------------------------------------
*
diff --git a/generic/tclInt.h b/generic/tclInt.h
index a336a53..399d83c 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -3476,8 +3476,9 @@ MODULE_SCOPE void * TclpThreadGetGlobalTSD(void *tsdKeyPtr);
MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp,
const char *msg, Tcl_Size length);
/* Tip 430 */
-MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp);
-MODULE_SCOPE int TclIsZipfsPath(const char *path);
+MODULE_SCOPE int TclZipfs_Init(Tcl_Interp *interp);
+MODULE_SCOPE int TclIsZipfsPath(const char *path);
+MODULE_SCOPE void TclZipfsFinalize(void);
MODULE_SCOPE int *TclGetUnicodeFromObj(Tcl_Obj *, int *);
MODULE_SCOPE Tcl_Obj *TclNewUnicodeObj(const int *, int);
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c
index befcc7d..14da083 100644
--- a/generic/tclZipfs.c
+++ b/generic/tclZipfs.c
@@ -319,10 +319,12 @@ static int InitWritableChannel(Tcl_Interp *interp,
ZipChannel *info, ZipEntry *z, int trunc);
static int ListMountPoints(Tcl_Interp *interp);
static int ContainsMountPoint(const char *path, int pathLen);
-static void SerializeCentralDirectoryEntry(
- const unsigned char *start,
- const unsigned char *end, unsigned char *buf,
- ZipEntry *z, size_t nameLength);
+static void CleanupMount(ZipFile *zf);
+static void SerializeCentralDirectoryEntry(const unsigned char *start,
+ const unsigned char *end,
+ unsigned char *buf,
+ ZipEntry *z,
+ size_t nameLength);
static void SerializeCentralDirectorySuffix(
const unsigned char *start,
const unsigned char *end, unsigned char *buf,
@@ -364,10 +366,7 @@ static int ZipFSLoadFile(Tcl_Interp *interp, Tcl_Obj *path,
Tcl_FSUnloadFileProc **unloadProcPtr, int flags);
static int ZipMapArchive(Tcl_Interp *interp, ZipFile *zf,
void *handle);
-static void ZipfsExitHandler(void *clientData);
-static void ZipfsMountExitHandler(void *clientData);
static void ZipfsSetup(void);
-static void ZipfsFinalize(void);
static int ZipChannelClose(void *instanceData,
Tcl_Interp *interp, int flags);
static Tcl_DriverGetHandleProc ZipChannelGetFile;
@@ -1906,7 +1905,6 @@ ZipFSCatalogFilesystem(
*/
zf->mountPoint = (char *) Tcl_GetHashKey(&ZipFS.zipHash, hPtr);
- Tcl_CreateExitHandler(ZipfsMountExitHandler, zf);
zf->mountPointLen = strlen(zf->mountPoint);
zf->nameLength = strlen(zipname);
@@ -2154,7 +2152,6 @@ ZipfsSetup(void)
ckalloc(strlen(ZIPFS_FALLBACK_ENCODING) + 1);
strcpy(ZipFS.fallbackEntryEncoding, ZIPFS_FALLBACK_ENCODING);
ZipFS.initialized = 1;
- Tcl_CreateExitHandler(ZipfsExitHandler, NULL);
}
/*
@@ -2208,6 +2205,41 @@ ListMountPoints(
}
/*
+ *------------------------------------------------------------------------
+ *
+ * CleanupMount --
+ *
+ * Releases all resources associated with a mounted archive. There
+ * must not be any open files in the archive.
+ *
+ * Caller MUST be holding WriteLock() before calling this function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory associated with the mounted archive is deallocated.
+ *------------------------------------------------------------------------
+ */
+static void
+CleanupMount(ZipFile *zf) /* Mount point */
+{
+ ZipEntry *z, *znext;
+ Tcl_HashEntry *hPtr;
+ for (z = zf->entries; z; z = znext) {
+ znext = z->next;
+ hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name);
+ if (hPtr) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ if (z->data) {
+ ckfree(z->data);
+ }
+ ckfree(z);
+ }
+}
+
+/*
*-------------------------------------------------------------------------
*
* DescribeMounted --
@@ -2349,6 +2381,7 @@ TclZipfs_MountBuffer(
{
ZipFile *zf;
+ /* TODO - how come a *read* lock suffices for initialzing ? */
ReadLock();
if (!ZipFS.initialized) {
ZipfsSetup();
@@ -2439,7 +2472,6 @@ TclZipfs_Unmount(
const char *mountPoint) /* Mount point path. */
{
ZipFile *zf;
- ZipEntry *z, *znext;
Tcl_HashEntry *hPtr;
Tcl_DString dsm;
int ret = TCL_OK, unmounted = 0;
@@ -2477,19 +2509,9 @@ TclZipfs_Unmount(
* still cleaning things up.
*/
- for (z = zf->entries; z; z = znext) {
- znext = z->next;
- hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, z->name);
- if (hPtr) {
- Tcl_DeleteHashEntry(hPtr);
- }
- if (z->data) {
- ckfree(z->data);
- }
- ckfree(z);
- }
+ CleanupMount(zf);
ZipFSCloseArchive(interp, zf);
- Tcl_DeleteExitHandler(ZipfsMountExitHandler, zf);
+
ckfree(zf);
unmounted = 1;
@@ -6203,6 +6225,7 @@ ZipfsAppHookFindTclInit(
return TCL_ERROR;
}
#endif
+#ifdef OBSOLETE
static void
ZipfsExitHandler(
@@ -6222,15 +6245,49 @@ ZipfsExitHandler(
}
}
}
+#endif
-static void
-ZipfsFinalize(void) {
- Tcl_FSUnregister(&zipfsFilesystem);
- Tcl_DeleteHashTable(&ZipFS.fileHash);
- ckfree(ZipFS.fallbackEntryEncoding);
- ZipFS.initialized = -1;
+void TclZipfsFinalize(void)
+{
+ /*
+ * Finalization steps:
+ * For every mounted archive, if it no longer has any open handles
+ * clean up the mount and associated zip file entries.
+ * If there are no more mounted archives, clean up and free the
+ * ZipFS.fileHash and ZipFS.zipHash tables.
+ */
+ WriteLock();
+
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch zipSearch;
+ for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &zipSearch); hPtr;
+ hPtr = Tcl_NextHashEntry(&zipSearch)) {
+ ZipFile *zf = (ZipFile *) Tcl_GetHashValue(hPtr);
+ if (zf->numOpen == 0) {
+ Tcl_DeleteHashEntry(hPtr);
+ CleanupMount(zf);
+ ZipFSCloseArchive(NULL, zf);
+ ckfree(zf);
+ }
+ }
+
+ hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &zipSearch);
+ if (hPtr == NULL) {
+ hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &zipSearch);
+ if (hPtr == NULL) {
+ /* Both hash tables empty. Free them */
+ Tcl_DeleteHashTable(&ZipFS.fileHash);
+ Tcl_DeleteHashTable(&ZipFS.zipHash);
+ Tcl_FSUnregister(&zipfsFilesystem);
+ ckfree(ZipFS.fallbackEntryEncoding);
+ ZipFS.initialized = -1;
+ }
+ }
+
+ Unlock();
}
+#ifdef OBSOLETE
static void
ZipfsMountExitHandler(
void *clientData)
@@ -6250,6 +6307,7 @@ ZipfsMountExitHandler(
}
}
+#endif
/*
*-------------------------------------------------------------------------