System.AccessViolationException on Paper Jam

Issue #57 new
Keith Platter created an issue

When scanning using fujitsu fi-7160 driver, NTwain 3.3.8 and TWAINDSM 2.3.0, I recieve the following error when a paper jam occurs.

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at NTwain.Triplets.Dsm.NativeMethods.DsmWinNew(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, TWPendingXfers da ta) at NTwain.Triplets.Dsm.DsmEntry(TWIdentity origin, TWIdentity destination, Me ssage msg, TWPendingXfers data) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain \Triplets\Dsm.cs:line 275 at NTwain.Triplets.PendingXfers.EndXfer(TWPendingXfers pendingXfers) in C:\Us ers\yinch\Source\Repos\ntwain\src\NTwain\Triplets\DGControl\DGControl.PendingXfe rs.cs:line 22 at NTwain.Internals.TransferLogic.DoTransferRoutine(ITwainSessionInternal ses sion) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Internals\TransferLogic.c s:line 100 at NTwain.TwainSession.HandleSourceMsg(Message msg) in C:\Users\yinch\Source\ Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 293 at NTwain.TwainSession.<>c__DisplayClass34_0.<HandleCallback>b__0() in C:\Use rs\yinch\Source\Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 275 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callba ck, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, De legate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Objec t state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionCo ntext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C ontextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C ontextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, In tPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callba ck, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, De legate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority pr iority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wPara m, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at NTwain.Internals.InternalMessageLoopHook.<>c__DisplayClass3_1.<Start>b__0( ) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Internals\InternalMessageLoop Hook.cs:line 45 at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionCo ntext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C ontextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C ontextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

Comments (8)

  1. Keith Platter reporter

    When the paper jam occurs, the TransferReady event is fired before the TransferError event, If I set CancelAll to true in the TransferReady event it does not throw the System.AccessViolationException error.

    If I do not set CancelAll to true, after the TransferError event is called, it calls the TransferReady event again, this time if I set CancelAll to true it only prevents the error about half the time. Watching the state in StateChanged it usually goes from 6 to 4 when it is going to fail, if it goes 6,5,4 it seems to work.

    I am not sure if that helps any. I also found that it does not matter if PreferNewDSM is set to false I also get the same error but this time on the call to DsmWinOld

  2. Eugene Wang repo owner

    Not sure if there's a difference is between jam on first transfer or during multi-page transfer. In any event I added a flag on TwainSession that may help in this case if it still happens with the 3.3.9. If not I'll have to do more digging.

    // set this
    session.StopOnTransferError = true;
    
  3. Keith Platter reporter

    With the 3.3.9 update the TransferError event is never called, regardless of whether or not StopOnTransferError is set to true.

    If StopOnTransferError is set to true, I still receive the AccessViolationException error, if it is not set to true then I get the following error...

    System.Runtime.InteropServices.SEHException was unhandled HResult=-2147467259 Message=External component has thrown an exception. Source=NTwain ErrorCode=-2147467259 StackTrace: at NTwain.Triplets.PendingXfers.Reset(TWPendingXfers pendingXfers) at NTwain.TwainSession.<>c__DisplayClass85_0.<ForceStepDown>b__0() in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSession.cs:line 400 at NTwain.Internals.InternalMessageLoopHook.Invoke(Action action) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Internals\InternalMessageLoopHook.cs:line 76 at NTwain.TwainSession.ForceStepDown(Int32 targetState) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSession.cs:line 392 at NTwain.TwainSession.HandleSourceMsg(Message msg) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 311 at NTwain.TwainSession.<>c__DisplayClass34_0.<HandleCallback>b__0() in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 275 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at NTwain.Triplets.Dsm.NativeMethods.DsmWinNew(TWIdentity origin, TWIdentity destination, DataGroups dg, DataArgumentType dat, Message msg, TWPendingXfers data) at NTwain.Triplets.Dsm.DsmEntry(TWIdentity origin, TWIdentity destination, Message msg, TWPendingXfers data) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Triplets\Dsm.cs:line 275 at NTwain.Triplets.PendingXfers.EndXfer(TWPendingXfers pendingXfers) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Triplets\DGControl\DGControl.PendingXfers.cs:line 23 at NTwain.Internals.TransferLogic.DoTransferRoutine(ITwainSessionInternal session) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Internals\TransferLogic.cs:line 109 at NTwain.TwainSession.HandleSourceMsg(Message msg) in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 293 at NTwain.TwainSession.<>c__DisplayClass34_0.<HandleCallback>b__0() in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\TwainSessionInternal.cs:line 275 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.Run() at NTwain.Internals.InternalMessageLoopHook.<>c__DisplayClass3_1.<Start>b__0() in C:\Users\yinch\Source\Repos\ntwain\src\NTwain\Internals\InternalMessageLoopHook.cs:line 45 at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

  4. Keith Platter reporter

    I am debugging the issue and have found that the error occurs before line 113 in TransferLogic.cs

    113 if (rc != ReturnCode.Success && session.StopOnTransferError)

    so the StopOnTransferError flag is never checked. The error occurs on line 109 in TransferLogic.cs

    109 rc = session.DGControl.PendingXfers.EndXfer(pending);

    EndXfer has already been called at this point 2 times and for some reason this call fails with the AccessViolationException

    If I replace lines 104 thru 121 with

    if (rc == ReturnCode.Success || !session.StopOnTransferError) { rc = session.DGControl.PendingXfers.EndXfer(pending); }

    it works with the exception that I dont recieve a TransferError event.

    I think the original problem may be related to the state the Dsm was in when EndXfer is called. In the old 3.3.8 version when it is called the first time from DoTransferRoutine it is in state 6 and works, it is then called again from a CloseDSReq msg in HandleSourceMsg at which point it is still a 6 works, the CoseDSReq msg forces state to a 4, somehow DsmEntry with a msg of EndXfer is then called again and the AccessViolationException is thrown because state is now a 3

  5. Keith Platter reporter

    Ok, I think I halfway understand it now. After the First call to EndXfer the CloseDSReq msg is recieved causing the ForceStepDown to call EndXfer a second time. At that point the session state is still a 6 so the Session.VerifyState(6, 7...) still passes, but as the state is lowered to a 3 one of the calls to Dsm.DsmEntry(msg=EndXfer) fails. I noticed there was a hack in TwainSessionInternal.DisableSource for possibly something similar.

  6. Eugene Wang repo owner

    The first EndXfer on line 109 totally shouldn't be there (oops). I also made some more tweaks on who calls DisableSource so ForceStepDown is no longer used (was always a dangerous method), but who knows ¯_(ツ)_/¯

  7. Keith Platter reporter

    That change does seem to stop the error from occuring. Thanks :)

    Two questions though... I tried it with and without the StopOnTransferError = true, and it worked both ways. Is StopOnTransferError even needed now? The call to EndXfer sets rc = success when StopOnTransferError is false but since in the loop while (rc == ReturnCode.Success && pending.Count != 0 && !session.CloseDSRequested); pending.Count == 0 it exits the loop anyway. Just wondering...

    Also should the TransferError event be raised at some point in the process? Possibly after line 47 in DoTransferRoutine where var rc = session.DGControl.PendingXfers.Get(pending) .... Acording to the PendingXfers.Get function / specs a pending.count at this point of 0 should be a failure (and in this case the driver is returning a success)?

  8. Eugene Wang repo owner

    I'm leaving StopOnTransferError in just in case since not all sources can be counted on to follow specs and may leave pending count != 0.

    It'll raise error if a non-success code is returned (see HandleReturnCode method), otherwise it's not an error from the source's view so raising an error event wouldn't work since the source status will likely just say ok as well (helps nobody). The spec actually says "If there is no current this call must return TWRC_FAILURE / TWCC_SEQERROR". Theoretically if the stop is due to paper jam it would return error code and in the event status I can get the PaperJam code, but not all sources do that.

  9. Log in to comment