CR: Error handler for filesystem exception due to usb disk unplug
"Zhao, Halley" <[email protected]>
| Newsgroups | gmane.comp.multimedia.helix.devel |
|---|---|
| Message-ID | <094BCE01AFBE9646AF220B0B3F367AAB03499F5B@pdsmsx413.ccr.corp.intel.com> |
I'm not familiar with file system plugin, please kindly review the patch and give your suggestion.
Great thanks.
Synopsis:
The patch fix bug #8471: Device hang up after play music from USB then plug out and plug in the USB.
I added error handle for usb disk unplug exception.
Overview:
Memory map is used in helix plugin for file io, In GetBlock() of common/fileio/mmapmgr.cpp,
the pBuffer address is calculated from the memory page information. it may be invalid due to the device being removed;
then when there is a memcpy() in the future, it will crash the engine.
On Windows system, it tests IsBadReadPtr()to catch the exception as early as possible.
But there is no such check (error handle) for Linux platform. I added a function to act as IsBadReadPtr() to catch the exception.
After memory map exception (MMAP_EOF_EXCEPTION) occurred, the Read() function in common/fileio/platform/unix/mmapdatf.cpp
will regress to normal_read. and it will consume some data which has been mapped in memory.
then in CheckForCorruptFile() of filesystem/local/full/smplfsys.cpp, we should try to consider this situation.
and in this scenario file size (m_ulSize) isn't initialized. We could determine it is a corrupt file depends on m_ulSize equal to 0.
Files Added:
No file added
Files Modified:
common/fileio/mmapmgr.cpp
add function _IsBadReadPtr() to detect whether the file is available, and try to catch the exception due to device removed.
filesystem/local/full/smplfsys.cpp
file size (m_ulSize) equal to 0 means a corrupt file.
Image Size and Heap Use impact (Client -Only):
little
Platforms and Profiles Affected:
platform: linux-2.2-libc6-gcc32-i586
profile: helix-client-all-defines
Distribution Libraries Affected:
<smplfsys.so>
Distribution library impact and planned action:
<None>
Platforms and Profiles Build Verified:
Set BIF branch -> hxclient_3_1_0_atlas_restricted
Set Target(s) -> player_mid_all_installers (or splay)
Set Profile -> helix-client-all-defines
System ID -> linux-2.2-libc6-gcc32-i586
Branch:
HEAD
Copyright assignment: <MUST be one of the following statements >
2. Intel has signed and delivered a Joint Copyright Assignment
to RealNetworks, and received acknowledgment that the
agreement was received.
Files Attached:
common-fileio-mmapmgr.cpp.diff.txt
filesystem-local-smplsys.cpp.diff.txt
ZHAO, Halley (Aihua)
Email: [email protected] <mailto:[email protected]>
Tel: +86(21)61166476
iNet: 8821-6476
SSG/OTC/UMD
_______________________________________________
Helix-client-dev mailing list
[email protected]
http://lists.helixcommunity.org/mailman/listinfo/helix-client-dev
filesystem-local-smplsys.cpp.diff.txt
(text/plain, 675 B)
Index: full/smplfsys.cpp
===================================================================
RCS file: /cvsroot/filesystem/local/full/smplfsys.cpp,v
retrieving revision 1.46.2.1
diff -u -w -r1.46.2.1 smplfsys.cpp
--- full/smplfsys.cpp 4 Feb 2008 05:49:53 -0000 1.46.2.1
+++ full/smplfsys.cpp 17 Jul 2008 05:05:08 -0000
@@ -1941,7 +1941,7 @@
ulDesiredReadCount = actual < m_ulPendingReadCount ? m_ulPendingReadCount-actual : 0;
}
- if (m_ulPos+ulDesiredReadCount <= m_ulSize)
+ if (m_ulPos+ulDesiredReadCount <= m_ulSize || m_ulSize == 0)
{
statusReturned = HXR_CORRUPT_FILE;
bErrorToBeReported = TRUE;
common-fileio-mmapmgr.cpp.diff.txt
(text/plain, 2.9 KB)
Index: mmapmgr.cpp
===================================================================
RCS file: /cvsroot/common/fileio/mmapmgr.cpp,v
retrieving revision 1.16
diff -u -w -r1.16 mmapmgr.cpp
--- mmapmgr.cpp 6 Jul 2007 20:35:11 -0000 1.16
+++ mmapmgr.cpp 17 Jul 2008 05:04:10 -0000
@@ -73,6 +73,8 @@
#if defined(_UNIX) && !defined(_BEOS)
#include <sys/mman.h>
#endif
+#include <setjmp.h>
+#include <signal.h>
#include "hxcom.h"
#include "hxtypes.h"
@@ -605,6 +607,43 @@
}
}
+static unsigned char g_ucCalledByTestRoutine = 0;
+static jmp_buf g_pBuf;
+
+void MemTestHandler ( int nSig) __attribute__ ((cdecl));
+void MemTestHandler ( int nSig)
+{
+ if ( g_ucCalledByTestRoutine )
+ {
+ longjmp ( g_pBuf, 1);
+ }
+
+
+}
+bool _IsBadReadPtr(const void* pv, unsigned long ulSize)
+{
+
+ char* pc;
+ void(*pPrev) ( int sig);
+
+ g_ucCalledByTestRoutine = 1;
+ if(setjmp ( g_pBuf))
+ {
+ return true;
+ }
+ pPrev = signal (SIGBUS, MemTestHandler);
+ if(pPrev == SIG_ERR)
+ {
+ printf("cant register my error handle\n");
+ }
+
+ pc = (char*) malloc ( ulSize);
+ memcpy ( pc, pv, ulSize);
+ g_ucCalledByTestRoutine = 0;
+ free(pc);
+ signal ( SIGBUS, pPrev);
+ return false;
+}
UINT32
MemoryMapManager::GetBlock(REF(IHXBuffer*) pBuffer, void* pHandle,
@@ -726,6 +765,38 @@
pEntry->pPage =
mmap(0, ulChunkSize, PROT_READ, MAP_PRIVATE,
pInfo->Descriptor, ulNeededPageNumber * m_ulChunkSize);
+ if (pEntry->pPage == 0)
+ {
+ pEntry->pPage = MAP_FAIL;
+ }
+ else
+ {
+ // When MapViewOfFile is called it returns a handle to a page of memory that
+ // the system no longer knows about so an exception occurs. It is usally a
+ // EXCEPTION_IN_PAGE_ERROR. Reading the documentation it appears that all access
+ // to handles returned from memory mapped I/O should be wrapped in try/catch blocks
+ // since the handles may be invalid. I added try/catch logic to test this out and
+ // it fixes the bug. The main problem I'm not sure about is that this code is also
+ // used by the server and IsBadReadPtr may iterate over the memory block which can
+ // be slow. Because this is the layer of code that "knows" it is using memory mapped
+ // I/O this is probably where the try/catch code belongs so that if an exception
+ // occurs then it can return an error and no buffer since the buffer wouldn't be
+ // accessible anyway.
+ HXBOOL bInvalid = TRUE;
+
+ try
+ {
+ bInvalid = _IsBadReadPtr(pEntry->pPage, ulChunkSize);
+ }
+ catch (...)
+ {
+ }
+
+ if (bInvalid)
+ {
+ pEntry->pPage = MAP_FAIL;
+ }
+ }
#else
pEntry->pPage = MapViewOfFile(pInfo->Descriptor, FILE_MAP_READ, 0,
ulNeededPageNumber * m_ulChunkSize, ulChunkSize);