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

Access Violation sometimes when trying to draw rectangles #1137

Closed
musictopia2 opened this issue Feb 10, 2020 · 28 comments
Closed

Access Violation sometimes when trying to draw rectangles #1137

musictopia2 opened this issue Feb 10, 2020 · 28 comments
Milestone

Comments

@musictopia2
Copy link

musictopia2 commented Feb 10, 2020

Description
When using skiasharp to draw rectangles, it gives access violation error.
This happens when I do from wpf and I use the SkElement and the first time it triggers the PaintSurface Event.

Code

on wpf is this

    private void PaintSurface(object? sender, SKPaintSurfaceEventArgs e)
    {
        Execute.OnUIThread(() =>
        {
            e.Surface.Canvas.Clear();
            _thisSquare.DrawSquare(e.Surface.Canvas, e.Info.Width, e.Info.Height);

        });
    }

on cross platform is this

    public void DrawSquare(SKCanvas thisCanvas, float width, float height)
    {

        var bounds = SKRect.Create(0, 0, width, height);
        _redPenBrush!.StrokeWidth = bounds.Width / 20;
        _slateGrayPenBrush!.StrokeWidth = bounds.Width / 30;
        _blackPenBrush!.StrokeWidth = bounds.Width / 20;
        _darkGrayPenBrush!.StrokeWidth = bounds.Width / 30;
        MiscHelpers.DefaultFont = "Verdana";
        var thisPercs = MiscHelpers.EnumLinearGradientPercent.Angle45;
        if (IsFlipped == true)
        {
            if (IsMine == true || Flagged == true)
            {
                var firstColor = new SKColor(255, 255, 255, 100);
                var secondColor = new SKColor(0, 0, 0, 100);
                var secondBrush = MiscHelpers.GetLinearGradientPaint(firstColor, secondColor, bounds, thisPercs);
                thisCanvas.DrawOval(bounds.Left + (bounds.Width / 2), bounds.Top + (bounds.Width / 2), bounds.Width / 4, bounds.Height / 4, _redSolidBrush);
                // well see how the second part comes along (could be iffy)(?)
                thisCanvas.DrawOval(bounds.Left + (bounds.Width / 2), bounds.Top + (bounds.Width / 2), bounds.Width / 4, bounds.Height / 4, secondBrush);
            }
            else if (NeighborMines > 0)
            {
                var textPaint = MiscHelpers.GetTextPaint(SKColors.Aqua, (bounds.Height * 3) / 4);
                thisCanvas.DrawCustomText(NeighborMines.ToString(), TextExtensions.EnumLayoutOptions.Center, TextExtensions.EnumLayoutOptions.Center, textPaint, bounds, out _); // i think
            }
            if (Flagged == true)
            {
                thisCanvas.DrawLine(bounds.Location.X, bounds.Location.Y, bounds.Location.X + bounds.Width, bounds.Location.Y + bounds.Height, _blackPenBrush);
                thisCanvas.DrawLine(bounds.Location.X + bounds.Width, bounds.Location.Y, bounds.Location.X, bounds.Location.Y + bounds.Height, _blackPenBrush);
            }
        }
        else
        {
            SKRect otherRect;
            otherRect = SKRect.Create(bounds.Location.X + (bounds.Width / 6), bounds.Location.Y + (bounds.Height / 6), (bounds.Width * 2) / 3, (bounds.Height * 2) / 3);
            SKColor firstColor;
            SKColor secondColor;
            SKPaint currentPaint;
            if (Pressed == true)
            {
                currentPaint = _darkGrayPenBrush;
                firstColor = new SKColor(0, 0, 0, 150);
                secondColor = new SKColor(255, 255, 255, 150);
            }
            else
            {
                currentPaint = _slateGrayPenBrush;
                firstColor = new SKColor(255, 255, 255, 150);
                secondColor = new SKColor(0, 0, 0, 150);
            }
            var tempPaint = MiscHelpers.GetLinearGradientPaint(firstColor, secondColor, bounds, thisPercs);
            thisCanvas.DrawRect(bounds, tempPaint);
            thisCanvas.DrawRect(otherRect, currentPaint);
            if (Flagged == true)
            {
                SKPath ThisPath = new SKPath();
                ThisPath.MoveTo(bounds.Location.X + (bounds.Width / 2), bounds.Location.Y + (bounds.Height / 4));
                ThisPath.LineTo(bounds.Location.X + ((bounds.Width * 3) / 4), bounds.Location.Y + ((bounds.Height * 3) / 8));
                ThisPath.LineTo(bounds.Location.X + (bounds.Width / 2), bounds.Location.Y + (bounds.Height / 2));
                thisCanvas.DrawPath(ThisPath, _redSolidBrush);
                thisCanvas.DrawLine(bounds.Location.X + (bounds.Width / 2), bounds.Location.Y + ((bounds.Height * 3) / 4), bounds.Location.X + (bounds.Width / 2), bounds.Location.Y + (bounds.Height / 4), _redPenBrush);
            }
        }
        thisCanvas.DrawRect(bounds, _slateGrayPenBrush);
    }

the 2 lines causing the problem is this

thisCanvas.DrawRect(bounds, tempPaint);
thisCanvas.DrawRect(otherRect, currentPaint);

Expected Behavior
Expected behavior is to actually draw

Actual Behavior
Access violation on one of the 2 lines of code

thisCanvas.DrawRect(bounds, tempPaint);
thisCanvas.DrawRect(otherRect, currentPaint);

Basic Information

version is 1.68.1.1
with wpf.
however, the part that raise the error and won't let me handle it is the cross platform skiasharp.

@mattleibow
Copy link
Contributor

Is the Execute.OnUIThread blocking? If not (which is likely) the canvas will actually be disposed and you are now trying to access something that is gone from memory.

On this note, why are you using the Execute.OnUIThread method? The paint callback should already be on the UI thread. You shouldn't need to use any additional logic to move it.

@musictopia2
Copy link
Author

I actually tried the same code on the 16.8.0 and the problem did not happen. I did the OnUIThread to try to fix the problem. Because when the problem first occured, I tried several things and same issue. I finally decided to try on an older version of skiasharp and the problem did not happen.

@mattleibow
Copy link
Contributor

Are you able to attach a full stack trace?
Are you using WPF with .NET Framework or .NET Core?

Does the issue still happen with 1.68.0 without the Execute.OnUIThread?

@musictopia2
Copy link
Author

How do I attach a full stack trace? I am using WPF with .net core. I tried without the OnUIThread and the problem did not reoccur with 1.68.0.
It would not even let me to do a try catch to try the drawings again with 1.68.1.1
Even with 1.68.0 I was using .WPF with .net core. I used

NU1701
code for the project so i don't get the warnings.

@musictopia2
Copy link
Author

I tried to run it again after changing over to the new version and here is what i was able to copy.
System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=
StackTrace:

@musictopia2
Copy link
Author

I checked the stack trace and it showed it as null. I did a screenshot but could not figure out how to send the screenshot. The problem would not happen every time but once in a while.

@mattleibow
Copy link
Contributor

You can just copy-paste the screenshot into the comments box. Or even drag the image into the comments. GitHub should just put the image in line.

@musictopia2
Copy link
Author

skiasharperror

@musictopia2
Copy link
Author

Thanks for letting me know. I tried that and worked. Here is the full screenshot now. You can see the stack trace actually showed null.

@mattleibow
Copy link
Contributor

Very interesting. Especially without the stack trace.

Are you able to create a minimal repro at all? I will help to get started.

@musictopia2
Copy link
Author

I need help with creating a minimum repro.
When the problem happens, the strange thing is it does not happen every time. Sometimes I can hit new game several times and no problems. Other times, it happens after 5 times. When I use the 1.68.0, the problem never happens. Do you think we can do a visual studio share. I do know that option is available where you see my code on my machine.

@musictopia2
Copy link
Author

One question. If you mean to create a repository of the solution I was working on, I can do that. What I would do is to copy/paste and make sure they are all the same folder and that would be the repository. If that would be helpful, I can do that then. What would happen is I would create it where you can always hit next game. You will see that sometimes, the issue would happen. But does not happen every time you do new game though. The cases where it happens, its always at the beginning of new game.

@mattleibow
Copy link
Contributor

It would be great if you managed to get a repro with as little code as possible. Often just by trying to do that you see some weird things.

But, I am looking at the code that you have here and maybe something is being disposed...

thisCanvas.DrawRect(bounds, tempPaint);
thisCanvas.DrawRect(otherRect, currentPaint);

Is it randomly different ones crashing? Or is it always the second one?

Also, could it be that one of the paints _darkGrayPenBrush or _slateGrayPenBrush is being disposed?

What you can try and see if it is really this method that is failing is to replace the paints with new SKPaint() or the rects with SKRect.Create(10, 10) or something. This way you can remove any external code from the system.

And, another thing to try is to hit continue and see if there is another exception. Or check the output log for any info. Or, you can even check the "Common Language Runtime Exceptions" check box in the exceptions window. Maybe there is another exception that causes this exception.

The whole thing without the stack trace is weird.

One thing you can also try as well is using .NET Core. That might have a better exception.

The fact that there is no stack trace may mean that there is an issue with the version of .net framework. We are using portable pdbs, and .net framework should support it, but this file does say that there are a few issues: https://github.com/dotnet/core/blob/master/Documentation/diagnostics/portable_pdb.md Maybe bump the version to net472 or even 48...

@musictopia2
Copy link
Author

I was actually using .net core 3.1 in wpf.
I would hate to have to use the old framework and not the core.
Not sure if that could be an issue. I actually had to put some extra code in the project file to eliminate the warnings. The strange thing is the old version did not have the problem.
Are there plans to have a version that would support the wpf core without the warnings?

@alexandrvslv
Copy link
Contributor

alexandrvslv commented Mar 14, 2020

I have same behavior

  • Win 10 (many hosts)
  • Access Violation
  • Repeated randomly
  • DrawRect method
  • only 1.68.1.1
  • Xamarin.Forms 4.4
  • both UWP(10.0.17763.0) and WPF(net461)

Steps to reproduce:
1 On start the UI, cache it thread context: MainContext = SynchronizationContext.Current;
2 On paint method use readonly SKPaint paint variables. Calls ~500 DrawRect and DrawText (simple table) per invocation.
3 From background thread often and randomly call Invalidate:
MainContext.Post((state) =>((SKCanvasView)state).InvalidateSurface(), canvas);

@musictopia2
Copy link
Author

I now have a simple sample to show this always happening eventually.
My repository is here.
https://github.com/musictopia2/SkiaBugSample

To see it happening, just click new game. However, do several times. Eventually the error will occur. The problem did not happen with the 1.68.0.

@mattleibow
Copy link
Contributor

I think this may be related to #1121, which I am testing a fix with #1180.

I'll see if I can get feedback on that ASAP and then fix the rest of the views.

@mattleibow
Copy link
Contributor

mattleibow commented Mar 20, 2020

I have just published the PR (#1180) NuGet (1.68.2-pr.1180.4) to the preview feed: https://aka.ms/skiasharp-eap/index.json
This contains the fixes for macOS, iOS and Android. More platforms coming soon.

Give that a go and let me know if it fixes the crashes.

@musictopia2
Copy link
Author

How do I get the private feed one. I went to the preview on nuget and the latest version still showed 1.68.2-preview.43

@mattleibow
Copy link
Contributor

You need to att https://aka.ms/skiasharp-eap/index.json to the feeds for nuget. In VS add a new package source.

Check out this doc for a visual guide https://docs.microsoft.com/en-us/nuget/consume-packages/install-use-packages-visual-studio#package-sources

@musictopia2
Copy link
Author

sample

I followed to get the private feeds. Its still showing the same version that the nuget.org showed as you can see from the screenshot.

@mattleibow
Copy link
Contributor

Look in the drop down for 1.68.2-pr.1180.4 as this is a PR preview and it is somewhere in the middle of the previews

@musictopia2
Copy link
Author

I found it now. Just did not realize it would not be at the top. However, the same problem still occured even with that one. I was using windows 10 with wpf core.

@mattleibow
Copy link
Contributor

OK, might be something else. Is this link still the correct place?

https://github.com/musictopia2/SkiaBugSample

@musictopia2
Copy link
Author

This is still the correct place.

@mattleibow
Copy link
Contributor

This is now fixed and no longer crashes on 1.68.2-preview.50

@axel578
Copy link

axel578 commented Apr 21, 2020

@mattleibow
image
This is what i get when I call too much the InvalidateVisual() method of the SkElement, I used a SKGLControl to make context current and then used a Surface named 'Surface' to draw on it using the Gl context setted up previously, and I pass the 'Surface' snapshot SkImage to the SkElement and it gives me this : System.AccessViolationException Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I Looked at the GrContext made by the SKGLConttrol and it seems that the GPU memory ( called cache memory ) never gets free and is still growing ( some sort of memory leaks for the GPU ? )

@mattleibow
Copy link
Contributor

@axel578 I think that is another issue. It is most likely the image is actually a GPU image. Maybe try calling image.ToRasterImage to convert it to memory.

If that doesn't work, then please make a new issue. Thanks!

@mattleibow mattleibow added this to the v1.68.2 milestone Apr 29, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants