diff options
author | apnadkarni <apnmbx-wits@yahoo.com> | 2023-09-29 16:39:33 (GMT) |
---|---|---|
committer | apnadkarni <apnmbx-wits@yahoo.com> | 2023-09-29 16:39:33 (GMT) |
commit | 5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c (patch) | |
tree | f11cafbcf833276f3aa894797720253e5fd979c5 /generic | |
parent | c0f753dfae6d69344ff84eb052f91971f304e652 (diff) | |
download | tcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.zip tcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.tar.gz tcl-5d2cc9aa8096c724098eaa68d33bdbdbf11fda3c.tar.bz2 |
Refactor zipfs finalization
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIO.c | 3 | ||||
-rw-r--r-- | generic/tclInt.h | 5 | ||||
-rw-r--r-- | generic/tclZipfs.c | 114 |
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 /* *------------------------------------------------------------------------- |