Subscribe to News feed

A solution for SharePoint’s common DISP_E_EXCEPTION COM error

Posted at: 5:28 PM on 14 July 2009 by Muhimbi

SherlockAnother post from our ‘customer support archives’. We’ll call this one ‘The case where code executed by workflows behaves differently from code executed by Application pages and why it actually was our own fault’.

We were contacted by a SharePoint developer who is using our PDF Converter to convert files to PDF format from a SharePoint Designer workflow, a common requirement. This developer clearly knew what he was doing and decided to test the system under stress by activating the workflow on a number of files simultaneously, which resulted in a number of horrible SharePoint errors in the Event log, most notably the following ones:

Message: Exception occurred. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))
- Exception: System.Runtime.InteropServices.COMException
- StackTrace: at System.Runtime.InteropServices.ComTypes.IStream.Seek(Int64 dlibMove, Int32 dwOrigin, IntPtr plibNewPosition)
at Microsoft.SharePoint.SPFileStream.get_Position() …. etc

and

Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
- Exception: System.AccessViolationException
- StackTrace: at System.Runtime.InteropServices.ComTypes.IStream.Seek(Int64 dlibMove, Int32 dwOrigin, IntPtr plibNewPosition)
at Microsoft.SharePoint.SPFileStream.Seek(Int64 offset, SeekOrigin origin)
at Microsoft.SharePoint.SPFileCollection.AddInternal(String urlOfFile, Object file, PutFileOpt fileOpt, String createdBy, String modifiedBy, Int32 createdByID, Int32 modifiedByID, DateTime timeCreated, DateTime timeLastModified, Object varProperties, String checkInComment, SPVirusCheckStatus& virusCheckStatus, String& virusCheckMessage)
at Microsoft.SharePoint.SPFileCollection.Add(String urlOfFile, Stream stream, Hashtable properties, Boolean overwrite)

and the SharePoint trace log (in verbose mode) showed the following, all too familiar, messages

ERROR: request not found in the TrackedRequests. We might be creating and closing webs on different threads. ThreadId = 10, Free call stack =    at Microsoft.SharePoint.SPRequestManager.Release(SPRequest request)     at Microsoft.SharePoint.SPSite.Close()     at Microsoft.SharePoint.SPSite.Dispose()     at Microsoft.SharePoint.Workflow.SPWorkflowAutostartEventReceiver.AutoStartWorkflow(SPItemEventProperties properties, Boolean bCreate, Boolean bChange, AssocType atyp)     at Microsoft.SharePoint.Workflow.SPWorkflowAutostartEventReceiver.AutoStartWorkflow(SPItemEventProperties properties, Boolean bCreate, Boolean bChange)     at Microsoft.SharePoint.Workflow.SPWorkflowAutostartEventReceiver.ItemUpdated(SPItemEventProperties properties)     at Microsoft.SharePoint.SPEventManager.RunItemEvent...

and

An SPRequest object was not disposed before the end of this thread.  To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it.  This object will now be disposed.  Allocation Id: {1BA98355-FDFB-4757-92E6-644DD7CED638}  To determine where this object was allocated, create a registry key at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings.  Then create a new DWORD named SPRequestStackTrace with the value 1 under this key.    

and

36 heaps created, above warning threshold of 32. Check for excessive SPWeb or SPSite usage.

Anyone who has done any SharePoint development, including us, will immediately draw the conclusion that somewhere we are not disposing an SPWeb or SPSite object and if it wasn’t for the following we would agree.

  1. When invoking exactly the same code through a SharePoint Application Page, which is how our end-user - non workflow - interface works, everything works great. No errors, no warnings and no memory leaks.
     
  2. As part of our development process we thoroughly check our code for typical SharePoint dispose leaks using SPDisposeCheck. The PDF Converter comes out completely clean.
     
  3. When using an out-of-the-box Workflow Activity such as Copy List Item, you get the same ‘errors’ in the SharePoint trace log.
     
  4. A Google search for DISP_E_EXCEPTION SharePoint returns 1420 results, all from people tearing their hair out in despair. This problem appears to have many different causes and few common solutions.
  5.  

Bummer!

So, with a nice problem that only occurs under stress at hand we fired up our debuggers. Naturally it all works great when stepping through the code. We tried all kinds of common temporary workarounds such as a big mutex around the entire Workflow Activity, a couple of Sleeps in the code to let the system ‘recover’ and even acts of desperation such as manually calling the Garbage Collector (!)….. nada.

After stripping the code down to its bare minimum, removing all calls to anything remotely complex such as the actual PDF Conversion, we noticed that we were not disposing the stream that comes of our SPFile Object. After adding a Dispose() for that stream all problems went away.

using(Stream stream = someSPFileObject.OpenBinaryStream())
{
   … do your stuff
   stream.Close();
}

Why this is only a problem when invoked via workflows and why this has not turned up during our own stress tests is anyone's guess. We just hope that this solution will help anyone else with the same problem.

On a separate note, I would really like to thank our customers. They are extremely cooperative when it comes to troubleshooting these kinds of errors. They happily send log files, install interim versions while staying friendly and helpful. Thanks for making our lives a lot easier.

.






Labels: ,

5 Comments:

  • Maybe this is totally obvious to everyone else reading this post, but I don't understand why the explicit .Close() is required. The "using" statement takes care of disposing the stream object, right? Is there a key difference between .Close() and .Dispose()?

    By Blogger Jerkham, At 20 October, 2010 14:14  

  • Close() and Dispose() are not the same. However, Dispose() could call Close(), there is no official language guideline that says it MUST call it, it depends on the implementation.

    By Blogger Muhimbi, At 20 October, 2010 14:28  

  • Excellent post! And Kudos to your customers for realizing that every environment is different and you may not be able to replicate exactly what is happening in their environment - on yours. Those are the clients for which we in the IT development world would do anything.

    By Anonymous Anonymous, At 18 February, 2011 16:42  

  • Getting streams of files is still providing mixed results in SharePoint. Where possible we have switched to getting the entire byte array in one go using SPFile.OpenBinary.

    By Blogger Muhimbi, At 18 February, 2011 16:48  

  • I've been getting this same error following this sequence of events:
    Create a custom list from a list exported from SharePoint 2007 (xls), modify columns, import data using 3rd party tool, modify permissions, click inherit permissions and the error occurs. I'm not sure how or where to implement your fix or if it's even applicable. Any help is appreciated

    By Blogger Kim Killian, At 24 July, 2012 14:04  

Post a Comment

Subscribe to Post Comments [Atom]

Links to this post:

Create a Link