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

AccessViolationException errors #7

Closed
ThatRendle opened this issue May 31, 2014 · 8 comments
Closed

AccessViolationException errors #7

ThatRendle opened this issue May 31, 2014 · 8 comments

Comments

@ThatRendle
Copy link

I'm working on a version of my Flux web server using LibuvSharp: https://github.com/markrendle/flux/tree/libuv

My test console application works fine until I hit it with around 10,000 requests using weighttp -n 10000 -t 4 -c 8, at which point I start getting AccessViolationException thrown all over the place.

It also gets thrown sometimes when running the TcpFixture.Stress test (using R# test runner).

This is on a fairly monster PC, overclocked i7-4770, 32GB RAM, SSDs, etc.

I'm going to do some investigation of my own today, but thought I'd open an issue to get other eyes on the problem.

@txdv
Copy link
Owner

txdv commented May 31, 2014

One of the problems currently, that is not a problem on mono(or lets say it works on mono), is that the StaticEnd callback during long running applications will get collected

https://github.com/txdv/LibuvSharp/blob/master/LibuvSharp%2FUVFile.cs#L68

int r = uv_fs_close(loop.NativeHandle, fsr.Handle, FileDescriptor, FileSystemRequest.StaticEnd);

I'm using this everywhere. Now this code literally is the same as

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void uv_fs_cb(IntPtr IntPtr); // this is already in the code

int r = uv_fs_close(loop.NativeHandle, fsr.Handle, FileDescriptor, new uv_fs_cb(FileSystemRequest.StaticEnd)); // this is the literal translation

It creates a temporary delegate which gets collected therefore resulting in a faulty pointer therefore a probable AccessViolationException. I tried to create a static delegate which contains this function and is never collected, but then the Test just stop at some point, on mono as well as on the .net framework.

Didn't investigate it further yet, because it is hard to debug.

@txdv
Copy link
Owner

txdv commented May 31, 2014

This is one of the problems which keeps me releasing it on NuGet. A real headache.

@ThatRendle
Copy link
Author

It's because you're using an implicitly created delegate for the callback.

I changed CallbackPermaRequest in my in-project copy:

public static readonly Handle.callback StaticEnd = StaticEndImpl;

private static void StaticEndImpl(IntPtr ptr, int status)
{
    var obj = PermaRequest.GetObject<CallbackPermaRequest>(ptr);
    if (obj == null) {
        throw new Exception("Target is null");
    } else {
        obj.End(ptr, status);
    }
}

Seems to have fixed the problem, for my code at least.

@txdv
Copy link
Owner

txdv commented May 31, 2014

I did exactly the same without the readonly. Did you run the test suite? When I did that it would just stop at some point.

@kekekeks
Copy link

I've encountered a similar issue while writing bindings for evhttp. Try to use GCHandle.Alloc on the delegate like here https://github.com/kekekeks/evhttp-sharp/blob/master/EvHttpSharp/EventHttpListener.cs#L80

@terender
Copy link

I changed the CallbackPermaRequest like this

    internal class CallbackPermaRequest : PermaRequest
    {
        public Handle.callback CallbackDelegate;
        public CallbackPermaRequest(int size)
            : base(size)
        {
            CallbackDelegate = new Handle.callback(StaticEnd);
        }

        public CallbackPermaRequest(RequestType type)
            : this(UV.Sizeof(type))
        {
            CallbackDelegate = new Handle.callback(StaticEnd);
        }

        public Action<int, CallbackPermaRequest> Callback { get; set; }

        protected void End(IntPtr ptr, int status)
        {
            Callback(status, this);
            Dispose();
        }

        protected void StaticEnd(IntPtr ptr, int status)
        {
            var obj = PermaRequest.GetObject<CallbackPermaRequest>(ptr);
            if (obj == null) {
                throw new Exception("Target is null");
            } else {
                obj.End(ptr, status);
            }
        }
    }

then change the calling from

uv_write_unix(cpr.Handle, NativeHandle, buf, 1, CallbackPermaRequest.StaticEnd);

to

uv_write_unix(cpr.Handle, NativeHandle, buf, 1, cpr.CallbackDelegate);

In my case, it works fine both on Windows and on mono/Linux

@txdv
Copy link
Owner

txdv commented Nov 20, 2014

Do you mind making a pull request?

@txdv
Copy link
Owner

txdv commented Jan 22, 2015

@terender suggestion seems reasonable.

On mono these 'on the fly' delegates on static methods are actually saved forever. On the .NET framework they are not. My assumption was that they would stay, but I have fixed it in a commit that I have locally.

@txdv txdv closed this as completed in e39cfea Jan 22, 2015
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

4 participants