Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage 
Author Message
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage

Hello:

In the shell context menu handler that I am writing, I need to send
a variable size CStringArray from the handler to a program that the
handler launches prior to the interprocess communication (IPC).

The CStringArray is populated with the selected file paths from
Explorer.  When the list is small (under about 75 entries), there is
no problem.  But when I send a large number (lets say over 100)
it causes explorer to crash.

Interestingly, when debugging I put an AfxMessageBox("PreIPC")
just before the SendMessage that sends the pointer to the other
process.  After pressing OK the crash does not happen.  So it
looks like a delay at that point prevents the crash.  Of note, my
testbed is a Win2k SP2 system.

I know IPC usually requires some stringent synchronization, but I
don't see how it could be affecting this situation as only one
process at a time should be accessing the data.  I think this, because
the data is prepared before the other process is sent the message
to use it.

Below is some of the code that I use to accomplish this.  I replaced
some sections with comments for brevity:  (The other process
works with and frees the shared memory, but the crash comes
before the SendMessage is processed by the other process).

        // This code is from InvokeCommand() in the context menu handler
        // m_csaPaths is the CStringArchive that I am sending

        CMemFile file;
        CArchive ar(&file, CArchive::store, 40960);
        ASSERT(m_csaPaths.IsSerializable());
        m_csaPaths.Serialize(ar);
        ar.Close();
        DWORD dwLengthMemFile = file.GetLength();
        void *lpSerializedData = file.Detach();
        void *lpPathsStringArray;
        HANDLE hMem = ::CreateFileMapping((HANDLE)0xFFFFFFFF,
                NULL,PAGE_READWRITE,0, dwLengthMemFile,
                "DBFM_IPC_StringArray_FileMappingName");
        if (!hMem)      {       //      HANDLE ERROR    }
        lpPathsStringArray = ::MapViewOfFile(hMem,FILE_MAP_WRITE,0,0,0);
        if (!lpPathsStringArray)        {       //      HANDLE ERROR    }
        memcpy (lpPathsStringArray, lpSerializedData, dwLengthMemFile);
        hwndSoughtHandle = ::FindWindow(NULL, _T("DBFileMaker"));
        g_uintDBFM_IPC_Message = RegisterWindowMessage("WM_DBFM_IPC");
        if ((hwndSoughtHandle) && (g_uintDBFM_IPC_Message))
        {
                //      A pause here seems to resolve the issue
                ::SendMessage(hwndSoughtHandle, g_uintDBFM_IPC_Message,
                                (WPARAM)lpPathsStringArray,
                                (LPARAM)dwLengthMemFile);
        }
        else    
        {       //      HANDLE ERROR    }
        if (lpSerializedData)
                free(lpSerializedData);
        lpSerializedData = NULL;

I'd appreciate any insight into this.  This is my first project to use IPC
so I'm sure I'm breaking some rules for that.  Also, I've never been
particularly good at using CMemFile/CArchive, so I may have made
mistakes there as well.

Thank you,
Greg Gursky

--
Greg Gursky



Wed, 18 Feb 2004 03:48:31 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage

Quote:
> Hello:

> In the shell context menu handler that I am writing, I need to send
> a variable size CStringArray from the handler to a program that the
> handler launches prior to the interprocess communication (IPC).

> The CStringArray is populated with the selected file paths from
> Explorer.  When the list is small (under about 75 entries), there is
> no problem.  But when I send a large number (lets say over 100)
> it causes explorer to crash.

> Interestingly, when debugging I put an AfxMessageBox("PreIPC")
> just before the SendMessage that sends the pointer to the other
> process.  After pressing OK the crash does not happen.  So it
> looks like a delay at that point prevents the crash.  Of note, my
> testbed is a Win2k SP2 system.

> I know IPC usually requires some stringent synchronization, but I
> don't see how it could be affecting this situation as only one
> process at a time should be accessing the data.  I think this,
because
> the data is prepared before the other process is sent the message
> to use it.

> Below is some of the code that I use to accomplish this.  I replaced
> some sections with comments for brevity:  (The other process
> works with and frees the shared memory, but the crash comes
> before the SendMessage is processed by the other process).

> // This code is from InvokeCommand() in the context menu handler
> // m_csaPaths is the CStringArchive that I am sending

> CMemFile file;
> CArchive ar(&file, CArchive::store, 40960);
> ASSERT(m_csaPaths.IsSerializable());
> m_csaPaths.Serialize(ar);
> ar.Close();
> DWORD dwLengthMemFile = file.GetLength();
> void *lpSerializedData = file.Detach();
> void *lpPathsStringArray;
> HANDLE hMem = ::CreateFileMapping((HANDLE)0xFFFFFFFF,
> NULL,PAGE_READWRITE,0, dwLengthMemFile,
> "DBFM_IPC_StringArray_FileMappingName");
> if (!hMem) { // HANDLE ERROR }
> lpPathsStringArray = ::MapViewOfFile(hMem,FILE_MAP_WRITE,0,0,0);
> if (!lpPathsStringArray) { // HANDLE ERROR }
> memcpy (lpPathsStringArray, lpSerializedData, dwLengthMemFile);
> hwndSoughtHandle = ::FindWindow(NULL, _T("DBFileMaker"));
> g_uintDBFM_IPC_Message = RegisterWindowMessage("WM_DBFM_IPC");
> if ((hwndSoughtHandle) && (g_uintDBFM_IPC_Message))
> {
> // A pause here seems to resolve the issue
> ::SendMessage(hwndSoughtHandle, g_uintDBFM_IPC_Message,
> (WPARAM)lpPathsStringArray,
> (LPARAM)dwLengthMemFile);
> }
> else
> { // HANDLE ERROR }
> if (lpSerializedData)
> free(lpSerializedData);
> lpSerializedData = NULL;

> I'd appreciate any insight into this.  This is my first project to
use IPC
> so I'm sure I'm breaking some rules for that.  Also, I've never been
> particularly good at using CMemFile/CArchive, so I may have made
> mistakes there as well.

Dou you pass lpPathsStringArray to other process? How do you treat it
in other program? Pointer in app A has no any meaning in app B.
You should open file mapping in other process by calling to
OpenFileMapping/CreateFileMapping and only values that are valid
across process boundaries is offset from file mapping beginning and
file mapping size.


Wed, 18 Feb 2004 16:46:31 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage

Quote:
>Dou you pass lpPathsStringArray to other process? How do you treat it
>in other program? Pointer in app A has no any meaning in app B.

Dear Alex:

Thanks for your reply.

I was indeed passing lpPathsStringArray to the other process.  However,
that was just some old code that I forgot to remove.  I was not using it
on the other end.  I replaced the lpPathsStringArray in the SendMessage
with a NULL as it should have been.  Unfortunately, that did not resolve the
problem.  

The other process properly maps "DBFM_IPC_StringArray_FileMappingName"
and uses it.  When the number of file paths is small, it works fine, but when
sending a large number, it crashes.  Of note, its definately this process that
is crashing and not the process that the data is being sent to.  And it seems
its crashing during the SendMessage.  I have no way to debug inside the
SendMessage, however, to see specifically why its happening.

Also, calling an AfxMessageBox() right before the call to SendMessage seems
to remedy this.  I have no idea why.  It makes it sound like a timing issue, but
I dont see how timing can have anything to do with it since all the functions I'm
using are "blocking" functions. (The term doesn't exactly apply here, but I think
you know what I mean.)

I'd appreciate any further input you may be able to provide.  If you want to see
the OnIPCMessage() function from the other app, I'll be happy to post it, but I'm
pretty sure its not the cause of this problem.  I feel this, because if the crash
occurs that message handler in the other app actually never gets called.  

Thank you,
Greg

Quote:



>> Hello:

>> In the shell context menu handler that I am writing, I need to send
>> a variable size CStringArray from the handler to a program that the
>> handler launches prior to the interprocess communication (IPC).

>> The CStringArray is populated with the selected file paths from
>> Explorer.  When the list is small (under about 75 entries), there is
>> no problem.  But when I send a large number (lets say over 100)
>> it causes explorer to crash.

>> Interestingly, when debugging I put an AfxMessageBox("PreIPC")
>> just before the SendMessage that sends the pointer to the other
>> process.  After pressing OK the crash does not happen.  So it
>> looks like a delay at that point prevents the crash.  Of note, my
>> testbed is a Win2k SP2 system.

>> I know IPC usually requires some stringent synchronization, but I
>> don't see how it could be affecting this situation as only one
>> process at a time should be accessing the data.  I think this,
>because
>> the data is prepared before the other process is sent the message
>> to use it.

>> Below is some of the code that I use to accomplish this.  I replaced
>> some sections with comments for brevity:  (The other process
>> works with and frees the shared memory, but the crash comes
>> before the SendMessage is processed by the other process).

>> // This code is from InvokeCommand() in the context menu handler
>> // m_csaPaths is the CStringArchive that I am sending

>> CMemFile file;
>> CArchive ar(&file, CArchive::store, 40960);
>> ASSERT(m_csaPaths.IsSerializable());
>> m_csaPaths.Serialize(ar);
>> ar.Close();
>> DWORD dwLengthMemFile = file.GetLength();
>> void *lpSerializedData = file.Detach();
>> void *lpPathsStringArray;
>> HANDLE hMem = ::CreateFileMapping((HANDLE)0xFFFFFFFF,
>> NULL,PAGE_READWRITE,0, dwLengthMemFile,
>> "DBFM_IPC_StringArray_FileMappingName");
>> if (!hMem) { // HANDLE ERROR }
>> lpPathsStringArray = ::MapViewOfFile(hMem,FILE_MAP_WRITE,0,0,0);
>> if (!lpPathsStringArray) { // HANDLE ERROR }
>> memcpy (lpPathsStringArray, lpSerializedData, dwLengthMemFile);
>> hwndSoughtHandle = ::FindWindow(NULL, _T("DBFileMaker"));
>> g_uintDBFM_IPC_Message = RegisterWindowMessage("WM_DBFM_IPC");
>> if ((hwndSoughtHandle) && (g_uintDBFM_IPC_Message))
>> {
>> // A pause here seems to resolve the issue
>> ::SendMessage(hwndSoughtHandle, g_uintDBFM_IPC_Message,
>> (WPARAM)lpPathsStringArray,
>> (LPARAM)dwLengthMemFile);
>> }
>> else
>> { // HANDLE ERROR }
>> if (lpSerializedData)
>> free(lpSerializedData);
>> lpSerializedData = NULL;

>> I'd appreciate any insight into this.  This is my first project to
>use IPC
>> so I'm sure I'm breaking some rules for that.  Also, I've never been
>> particularly good at using CMemFile/CArchive, so I may have made
>> mistakes there as well.

--
Greg Gursky



Thu, 19 Feb 2004 04:09:18 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage


Wed, 18 Jun 1902 08:00:00 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage
Dear Alex (and anyone else following this thread):

I believe I've solved the problem.  I wasn't calling
UnmapViewOfFile() on the mapped data before
calling the SendMessage.  While I know I should
have done this, I'm still not sure why the crash
occurred in the SendMessage (which doesnt
send anything other than a notification to the
other process).

Anyways, calling
::UnmapViewOfFile(lpPathsStringArray);
after the memcpy seems to have solved it.  I ran
it on 9774 files I have in one of my directories and
it was fine.

Thanks Alex for your help.  It was your question
that got me investigating.

Sincerely,
Greg

--
Greg Gursky



Thu, 19 Feb 2004 04:47:06 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage


Wed, 18 Jun 1902 08:00:00 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage
Jumped the gun, it looks like.  On further testing
its still happening.

It seems to be happening with very very large
numbers of files (> approximately 5000) now.  It
seems to be intermittent now and requires many
more files than before, but it still happens. My
guess is that the unmap command is delaying
things just a touch so a larger list works out.

So while I can hardwire in a delay with a length
dependant on the size of the CStringArray, this
is hardly "proper" as its avoiding the problem and
not fixing it.

So if anyone can still see any error in my code (see
both the original post and my first reply to Alex) I'd
appreciate a heads-up.

Thanks,
Greg

--
Greg Gursky



Thu, 19 Feb 2004 05:15:37 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage

Quote:
> Jumped the gun, it looks like.  On further testing
> its still happening.

> It seems to be happening with very very large
> numbers of files (> approximately 5000) now.  It
> seems to be intermittent now and requires many
> more files than before, but it still happens. My
> guess is that the unmap command is delaying
> things just a touch so a larger list works out.

> So while I can hardwire in a delay with a length
> dependant on the size of the CStringArray, this
> is hardly "proper" as its avoiding the problem and
> not fixing it.

> So if anyone can still see any error in my code (see
> both the original post and my first reply to Alex) I'd
> appreciate a heads-up.

Hm.. Can it be something that related to number of files? 5000
filenames is a quite large number. Can it be stack overflow somewhere?


Thu, 19 Feb 2004 13:23:35 GMT  
 Crashing when sending a pointer to a large chunk of shared memory via an IPC SendMessage

Quote:
>Hm.. Can it be something that related to number of files? 5000
>filenames is a quite large number. Can it be stack overflow somewhere?

I'm not certain, that's for sure, but I really don't see why it would be.  It
seems the crash is occuring in the SendMessage.  The SendMessage
is simply sending a registered message and a number to another
application and really knows nothing about the shared data.

Also, if it were that, I don't understand why a pause (I think as little as
a couple of milliseconds) before the SendMessage stops the crash.
Even once without the pause it was able to handle over 9000 files
probably because the OS switched to another process right about that
point and slowed down the execution enough to allow it to run properly.

Also, I've used other applications that successfully handled that number
of files from a context menu (WinZip is one I can think of ATM) and while
I can't be sure they used shared memory for doing the IPC, I think it's likely.

Anyways, I'm starting to suspect it has nothing to do with the IPC at all
and perhaps it has to do with something with the SendMessage itself.
I need to check that the second process is perhaps not ready to
receive the registered message.  While the handle is valid perhaps
its not ready to accept a message via SendMessage.  But if this is true
I dont understand why the size of the CStringArray effects it since the
SendMessage really has nothing to do with the CStringArray or the
shared memory I fill with it.

And if all else fails I'll just introduce a waitable timer and pause it for
a half a second or something when the file list is large.  Thats going to
be a last resort, of course, as its avoiding the problem and not fixing
it.

Anyways, thanks for your help.

Sincerely,
Greg

--
Greg Gursky



Fri, 20 Feb 2004 00:01:53 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. IPC: Shared memory via dll vs memory map file

2. Shared memory and IPC in ansi C

3. ipc, shared memory

4. Help in Shared Memory(IPC), pipes

5. Sharing Memory across Processes via DLLs

6. Need to have two program sharing some memory via a DLL

7. Using larger shared memory segment

8. sending via network character pointers in structs

9. sharing memory (re-send)

10. Help need-Share memory crashed

11. Showing Call Stack and Determine which object is not valid LARGE CHUNK OF CODE

12. Good malloc routine for large chunks

 

 
Powered by phpBB® Forum Software