Better cleanup if PHYSFS_init() fails halfway through.
authorRyan C. Gordon <icculus@icculus.org>
Sun, 25 Mar 2012 16:13:23 -0400
changeset 1278 570b476e0230
parent 1277 f6996bfaec19
child 1279 5fc8dff2909b
Better cleanup if PHYSFS_init() fails halfway through.
src/physfs.c
--- a/src/physfs.c	Sun Mar 25 15:59:29 2012 -0400
+++ b/src/physfs.c	Sun Mar 25 16:13:23 2012 -0400
@@ -1132,9 +1132,9 @@
     assert(staticArchivers[numStaticArchivers - 1] == NULL);
 
     archiveInfo = (const PHYSFS_ArchiveInfo **) allocator.Malloc(len);
-    GOTO_IF_MACRO(!archiveInfo, PHYSFS_ERR_OUT_OF_MEMORY, failed);
+    BAIL_IF_MACRO(!archiveInfo, PHYSFS_ERR_OUT_OF_MEMORY, 0);
     archivers = (const PHYSFS_Archiver **) allocator.Malloc(len);
-    GOTO_IF_MACRO(!archivers, PHYSFS_ERR_OUT_OF_MEMORY, failed);
+    BAIL_IF_MACRO(!archivers, PHYSFS_ERR_OUT_OF_MEMORY, 0);
 
     for (i = 0; i < numStaticArchivers - 1; i++)
         archiveInfo[i] = staticArchivers[i]->info;
@@ -1143,16 +1143,11 @@
     memcpy(archivers, staticArchivers, len);
 
     return 1;
-
-failed:
-    allocator.Free(archiveInfo);
-    allocator.Free(archivers);
-    archivers = NULL;
-    archiveInfo = NULL;
-    return 0;
 } /* initStaticArchivers */
 
 
+static int doDeinit(void);
+
 int PHYSFS_init(const char *argv0)
 {
     BAIL_IF_MACRO(initialized, PHYSFS_ERR_IS_INITIALIZED, 0);
@@ -1160,31 +1155,29 @@
     if (!externalAllocator)
         setDefaultAllocator();
 
-    if (allocator.Init != NULL)
-        BAIL_IF_MACRO(!allocator.Init(), ERRPASS, 0);
-
-    BAIL_IF_MACRO(!__PHYSFS_platformInit(), ERRPASS, 0);
-
-    BAIL_IF_MACRO(!initializeMutexes(), ERRPASS, 0);
+    if ((allocator.Init != NULL) && (!allocator.Init())) return 0;
+
+    if (!__PHYSFS_platformInit())
+    {
+        if (allocator.Deinit != NULL) allocator.Deinit();
+        return 0;
+    } /* if */
+
+    /* everything below here can be cleaned up safely by doDeinit(). */
+
+    if (!initializeMutexes()) goto initFailed;
 
     baseDir = calculateBaseDir(argv0);
-    BAIL_IF_MACRO(!baseDir, ERRPASS, 0);
-
-    /* !!! FIXME: we have to clean up all the half-initialized state if something fails. */
+    if (!baseDir) goto initFailed;
 
     userDir = __PHYSFS_platformCalcUserDir();
-    if (!userDir)
-    {
-        allocator.Free(baseDir);
-        baseDir = NULL;
-        return 0;
-    } /* if */
+    if (!userDir) goto initFailed;
 
     /* Platform layer is required to append a dirsep. */
     assert(baseDir[strlen(baseDir) - 1] == __PHYSFS_platformDirSeparator);
     assert(userDir[strlen(userDir) - 1] == __PHYSFS_platformDirSeparator);
 
-    BAIL_IF_MACRO(!initStaticArchivers(), ERRPASS, 0);
+    if (!initStaticArchivers()) goto initFailed;
 
     initialized = 1;
 
@@ -1192,6 +1185,10 @@
     __PHYSFS_setError(PHYSFS_getLastErrorCode());
 
     return 1;
+
+initFailed:
+    doDeinit();
+    return 0;
 } /* PHYSFS_init */
 
 
@@ -1241,9 +1238,8 @@
 } /* freeSearchPath */
 
 
-int PHYSFS_deinit(void)
+static int doDeinit(void)
 {
-    BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, 0);
     BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), ERRPASS, 0);
 
     closeFileHandleList(&openWriteList);
@@ -1285,14 +1281,21 @@
     allowSymLinks = 0;
     initialized = 0;
 
-    __PHYSFS_platformDestroyMutex(errorLock);
-    __PHYSFS_platformDestroyMutex(stateLock);
+    if (errorLock) __PHYSFS_platformDestroyMutex(errorLock);
+    if (stateLock) __PHYSFS_platformDestroyMutex(stateLock);
 
     if (allocator.Deinit != NULL)
         allocator.Deinit();
 
     errorLock = stateLock = NULL;
     return 1;
+} /* doDeinit */
+
+
+int PHYSFS_deinit(void)
+{
+    BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, 0);
+    return doDeinit();
 } /* PHYSFS_deinit */