Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

ZipUtils thread-safe patch for #1562 #1933

Closed
wants to merge 1 commit into from

4 participants

@xeroo

Sorry for deleting #1924 by mistake.

Access to files from APK is improved in #1562. But modifying m_data in ZipUtils::getFileData has a thread-safety issue. This patch fixes it with a simple lock.

There maybe a better way. Please review.

@minggo
Owner

Why it has thread-safe issue?

@xeroo

CCFileUtils::getFileData uses s_pZipFile->getFileData to get data from apk, where s_pZipFile is a shared object. And m_data in s_pZipFile is used and modified inside s_pZipFile->getFileData which is also a shared object. The following lines from s_pZipFile->getFileData are exactly the point where thread-safe issue will happen.

    int nRet = unzGoToFilePos(m_data->zipFile, &fileInfo.pos);
    CC_BREAK_IF(UNZ_OK != nRet);

    nRet = unzOpenCurrentFile(m_data->zipFile);
    CC_BREAK_IF(UNZ_OK != nRet);

    pBuffer = new unsigned char[fileInfo.uncompressed_size];
    int nSize = 0;
    nSize = unzReadCurrentFile(m_data->zipFile, pBuffer, fileInfo.uncompressed_size);
@minggo
Owner

But cocos2d-x is not thread-safe.
It means that you can not invoke CCFileUtils::getFileData in more than one thread.

@xeroo

CCTextureCache::addImageAsync seems to be the standalone thread that uses CCFileUtils::getFileData. May be thread-safe should be guaranteed in CCImage::initWithImageFileThreadSafe, but it isn't.

@minggo
Owner

Yep, you are right.
So i think we should write thread-safe codes in CCImage::initWithImageFileThreadSafe, but not ZipUtils.

What's your opinion?

@xeroo

Sure, that seems the best solution. So, add a CCFileUtils::getFileDataThreadSafe function? Or, let CCFileUtils::getFileData use shared apk structure cache but separated offset data?

Maybe we should also ask @mingulov for his opinion?

@minggo
Owner

Or, let CCFileUtils::getFileData use shared apk structure cache but separated offset data?

How to do it?

@minggo
Owner

After detail reading the codes of ZipFile::getFileData(), i found there were two things may cause thread-safe problem
1. the operation of m_data->fileList
fileList is a map, and there are only read operations on it, so it is thread-safe.
2. unzXXX functions
these functions are all c functions, and there is not global variables and static variables in functions, so it is thread-safe.

All in a word, ZipFile::getFileData() is thread-safe.
Right?

@mingulov

No, for example unzGoToFilePos64 (called from unzGoToFilePos) is not thread-safe - it changes the provided 1st parameter - unzFile (m_data->zipFile - which is quite complex structure ) - so if ZipFile::getFileData will be called from 2 or more threads simultaneously - the behaviour is undefined.
So I think such mutexes might be useful.

But anyway, I think there is a problem with CCImage::initWithImageFileThreadSafe - as it really not a thread safe. The only difference with usual CCImage::initWithImageFile - is a missing call to fullPathForFilename(), but it is called at almost every CCFileUtils::getFileData - and CCFileUtils usually does not support different threads.

@minggo
Owner

@mingulov
Yep, you are right.

The key problem is because m_data is a shared object. But i don't think it is a good idea to add mutex in the function. Because it will slow down the speed even it is not needed.

The codes that will cause thread-safe issue is CCImage::initWithImageFileThreadSafe, so i think it is better only modify its codes, maybe not invoke getFileData.

What's your opinion?

@minggo
Owner

I have to close this PR, because it is not the best solution.
I have created an issue to track this bug.

Thank you for reporting this bug.

@minggo minggo closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 30, 2013
  1. @ccgoe

    ZipUtils thread-safe patch

    ccgoe authored
This page is out of date. Refresh to see the latest.
View
8 cocos2dx/support/zip_support/ZipUtils.cpp
@@ -312,10 +312,13 @@ ZipFile::ZipFile(const std::string &zipFile, const std::string &filter)
{
setFilter(filter);
}
+
+ pthread_mutex_init(&m_zipFileMutex, NULL);
}
ZipFile::~ZipFile()
{
+ pthread_mutex_destroy(&m_zipFileMutex);
if (m_data && m_data->zipFile)
{
unzClose(m_data->zipFile);
@@ -390,6 +393,8 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *
*pSize = 0;
}
+
+ pthread_mutex_lock(&m_zipFileMutex);
do
{
CC_BREAK_IF(!m_data->zipFile);
@@ -417,7 +422,8 @@ unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *
}
unzCloseCurrentFile(m_data->zipFile);
} while (0);
-
+ pthread_mutex_unlock(&m_zipFileMutex);
+
return pBuffer;
}
View
1  cocos2dx/support/zip_support/ZipUtils.h
@@ -154,6 +154,7 @@ namespace cocos2d
private:
/** Internal data like zip file pointer / file list array and so on */
ZipFilePrivate *m_data;
+ pthread_mutex_t m_zipFileMutex;
};
} // end of namespace cocos2d
#endif // __SUPPORT_ZIPUTILS_H__
Something went wrong with that request. Please try again.