Skip to content
Permalink
Browse files
Better cleanup if PHYSFS_init() fails halfway through.
  • Loading branch information
icculus committed Mar 25, 2012
1 parent 4cfd727 commit 107f07da97fbab4c20fdf6c05fdb7dbe7b99e450
Showing with 30 additions and 27 deletions.
  1. +30 −27 src/physfs.c
@@ -1132,9 +1132,9 @@ static int initStaticArchivers(void)
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,55 +1143,52 @@ static int initStaticArchivers(void)
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);

if (!externalAllocator)
setDefaultAllocator();

if (allocator.Init != NULL)
BAIL_IF_MACRO(!allocator.Init(), ERRPASS, 0);
if ((allocator.Init != NULL) && (!allocator.Init())) return 0;

BAIL_IF_MACRO(!__PHYSFS_platformInit(), ERRPASS, 0);
if (!__PHYSFS_platformInit())
{
if (allocator.Deinit != NULL) allocator.Deinit();
return 0;
} /* if */

BAIL_IF_MACRO(!initializeMutexes(), ERRPASS, 0);
/* everything below here can be cleaned up safely by doDeinit(). */

baseDir = calculateBaseDir(argv0);
BAIL_IF_MACRO(!baseDir, ERRPASS, 0);
if (!initializeMutexes()) goto initFailed;

/* !!! FIXME: we have to clean up all the half-initialized state if something fails. */
baseDir = calculateBaseDir(argv0);
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;

/* This makes sure that the error subsystem is initialized. */
__PHYSFS_setError(PHYSFS_getLastErrorCode());

return 1;

initFailed:
doDeinit();
return 0;
} /* PHYSFS_init */


@@ -1241,9 +1238,8 @@ static void freeSearchPath(void)
} /* 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 @@ int PHYSFS_deinit(void)
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 */


0 comments on commit 107f07d

Please sign in to comment.