Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.AccessViolationException #39

Closed
JohZant opened this issue Oct 21, 2019 · 19 comments
Closed

System.AccessViolationException #39

JohZant opened this issue Oct 21, 2019 · 19 comments

Comments

@JohZant
Copy link

JohZant commented Oct 21, 2019

I have recently started using IFilterTextReader to extract the text from all files in a document management system. I have created a windows service to get each document's byte array through a web service and process it.

using (Stream stream = new MemoryStream(byteArray))
using (var reader = new FilterReader(stream, extension, filterReaderOptions)) 
{
      text += reader.ReadToEnd();
}

I'm having a problem where I get a System.AccessViolationException at random times and my Windows Service just terminates.

I thought it was some of the documents at first, but the document that it broke on gets processed when I start the service back up again.

Here is the Stacktrace.
AccessViolationException.txt

Any idea what might be happening here?

@Sicos1977
Copy link
Owner

Are you using the code single or multithreaded?

@Sicos1977
Copy link
Owner

No response ... closed

@JohZant
Copy link
Author

JohZant commented Oct 23, 2019

I was using the code multithreaded, but all the objects that get the document stream and then use the FilterReader were created on the same thread. The only await that I had was on the method ProcessDocuments.

I spent the last day and a bit taking all the async code out and letting it run. No errors or issues so far. No idea what could have been making it thread unsafe.

@Sicos1977 Sicos1977 reopened this Oct 23, 2019
@Sicos1977
Copy link
Owner

The code inside IFilterTextReader has parts that are not thread safe. Something I want to fix in the near feature.

@JohZant
Copy link
Author

JohZant commented Oct 24, 2019

Looking at my logs from last night, I have found that there still seems to be some AccessViolationExceptions after my changes. I created a very basic console application this morning to test on, and I have the same thing popping up. The stack trace is a lot smaller this time and I have made sure that it is running single threaded.

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at IFilterTextReader.NativeMethods.IFilter.GetValue(IntPtr& pval)
   at IFilterTextReader.FilterReader.Read(Char[] buffer, Int32 index, Int32 count)
   at System.IO.TextReader.ReadToEnd()
   at System.IO.TextReader.SyncTextReader.ReadToEnd()
   at IV.Client.Connectors.IR.GetText(String AuthenticationString, Int32 DocumentID) in IV.Client.Connectors\IR.cs:line 453
   at IV.TestingConsole.Program.Main(String[] args) in IV.TestingConsole\Program.cs:line 69

I'm kind of just stabbing in the dark here. I've tried locking the stream and the reader and using StreamReader.Synchronized, which has been recommended to others on StackOverflow but I am still getting issues.

@CBergAccount
Copy link

Was there any solution to this? I am experiencing the same thing. Randomly happens. Seems most often with .doc. but a document working one time does not work Another.

Run in a separate thread but syncronosly.

@JohZant
Copy link
Author

JohZant commented Mar 17, 2020

This is my current solution until it gets fixed. Quite ugly and probably has ramifications that I haven't thought through well enough, but it seems to work for me. There are some parts that are probably not required, like the locks, but as they say, "If it ain't broke, don't fix it"

public class TextRetrieve
    {
        private readonly byte[] byteArray;

        public TextRetrieve(byte[] byteArray)
        {
            this.byteArray = byteArray;
        }


        [HandleProcessCorruptedStateExceptions]
        public string Retrieve(string extension)
        {
            string result = string.Empty;

            //put the contents into a stream to read
            int count = 0;
            while (count < 10)
            {
                Stream stream = null;
                FilterReader reader = null;
                try
                {
                    stream = new MemoryStream(byteArray);
                    lock (stream)
                    {
                        FilterReaderOptions filterReaderOptions = new FilterReaderOptions();
                        reader = new FilterReader(stream, extension, filterReaderOptions);
                        lock (reader)
                        {
                            string docText = string.Empty;
                            result = reader.ReadToEnd();
                            break;
                        }
                    }
                }
                catch (AccessViolationException)
                {
                    //do nothing, we are trying again
                    count++;
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    reader?.Dispose();
                    stream?.Dispose();
                }
            }
            return result;
        }
    }

Since I never had one specific document that would fail constantly, the class above tries to retrieve the text 10 times on AccessViolationException. I have only ever had it get to 3 times tried once. Every other time it gets it on the second go if it fails.

I use this class as follows:
var text = new TextRetrieve(byteArray).Retrieve(extension);

Hope this works alright for the time being. If you come up with a better solution, please let me know here.

@BergChristian
Copy link

Hi,

Thank you so much for sharing!

My problem is that the errors takes down my whole application.
HandleProcessCorruptedStateExceptions, does this solve that problem?

@JohZant
Copy link
Author

JohZant commented Mar 18, 2020

Read about it here: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.exceptionservices.handleprocesscorruptedstateexceptionsattribute?view=netframework-4.8

[HandleProcessCorruptedStateExceptions] allows you to catch AccessViolationException in the method.

@BergChristian
Copy link

Thank you! I read in the mean time. I did not know about this, but it saves me a a lot of problems. Gold star and a big thank you!

@BergChristian
Copy link

and... totally irrelevant, but hey, it is Corona times, a lot of things feels irrelevant. Love Australia. Like my second home from Sweden. Stay safe.

@JohZant
Copy link
Author

JohZant commented May 19, 2020

@Sicos1977, has there been an update to fix this issue?

@Sicos1977
Copy link
Owner

I have no idea where to look for this so also no idea how to solve this. I need a good crash report to investigate this.

@Sicos1977
Copy link
Owner

I change the code a little bit, I added some code to free the pointer. So get the latest code from GitHub and see if this solves the problem.

                        var valuePtr = IntPtr.Zero;

                        try
                        {
                            var valueResult = _filter.GetValue(ref valuePtr);
                        
                            CheckResult(valueResult);

                            switch (valueResult)
                            {
                                case NativeMethods.IFilterReturnCode.FILTER_E_NO_MORE_VALUES:
                                case NativeMethods.IFilterReturnCode.FILTER_E_NO_VALUES:
                                    _chunkValid = false;
                                    break;

                                case NativeMethods.IFilterReturnCode.S_OK:
                                case NativeMethods.IFilterReturnCode.FILTER_S_LAST_VALUES:
                                    var temp = GetPropertyNameAndValue(valuePtr);
                                    if (!string.IsNullOrEmpty(temp))
                                    {
                                        textBuffer = temp.ToCharArray();
                                        textLength = (uint) textBuffer.Length;
                                        textRead = true;
                                    }
    
                                    _chunkValid = false;
                                    break;
                            }
                        }
                        finally
                        {
                            if (valuePtr != IntPtr.Zero)
                                Marshal.Release(valuePtr);
                        }

@Sicos1977 Sicos1977 reopened this May 19, 2020
@Sicos1977
Copy link
Owner

I just released IFilterTextReader 1.6.6 to nuget.

@Sicos1977
Copy link
Owner

Please let me know if this makes any differences

@JohZant
Copy link
Author

JohZant commented May 19, 2020

I'll do some testing when I get a chance and get back to you. Thank you very much for the update .

@Sicos1977
Copy link
Owner

And?

@filipnavara
Copy link
Contributor

If you can produce a memory dump at the time of the crash I'd be happy to look into it. Windows has feature to generate the memory dumps on application crash, it can be enabled in registry. Additionally, we have analyzed 3 AV crashes from our customers in the last 2 days. Two of them have the same underlying cause (#41), the third one is different crash with the same Office filter that was reported to Microsoft (https://aka.ms/AA8lcfh).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants