Quantcast
Channel: Active questions tagged crash - Stack Overflow
Viewing all articles
Browse latest Browse all 7190

P/Invoke on Mac causes process to exit

$
0
0

I'm attempting to build a utility to automatically copy files from removable drives (specifically, an SD card from my camera) when they are attached. I've built most of the plumbing and it successfully detects when a card is present, scans it for files, and copies them to my desired location.

I want to have copy progress notifications as well, and that's not possible with the standard File.CopyTo implementation provided in .NET so I built my own platform specific copy providers that report progress updates.

I found a lovely library provided by Miguel de Icaza that exposes Mac's native copyfile function here: https://github.com/migueldeicaza/Darwin.CopyFile

The library copies files just fine, but the second I try to set a state callback, the process just exits with return code 0.

The code in question looks like this:

public async Task Copy(IngestionOperation operation, CancellationToken cancellationToken){    using var state = new State();    state.SetStatusCallback((Progress what, Stage stage, string source, string dest, State state) =>    {        if (cancellationToken.IsCancellationRequested)        {            return NextStep.Quit;        }        if (CopyProgress == null)        {            return NextStep.Continue;        }        if (stage == Stage.Progress)        {            CopyProgress.Invoke(this, new CopyProgressEventArgs(operation.Source.FullName, operation.Destination, operation.Source.Length, state.Copied));        }        return NextStep.Continue;    });    var flags = Flags.Clone;    if (operation.Overwrite)    {        flags |= Flags.Unlink;    }    var destinationFileInfo = FileSystem.FileInfo.FromFileName(operation.Destination);    destinationFileInfo.Directory.Create();    var status = await Task.Run(() => Darwin.CopyFile.Copy(operation.Source.FullName, operation.Destination, Flags.Clone, state));    if (status != Status.Ok)    {        if (status == Status.EACCESS)        {            throw new UnauthorizedAccessException("CopyFile returned EACCESS");        }        throw new MacOsCopyException(status);    }}

The only way I can get this code to execute at the moment, is to comment out the state.SetStatusCallback call and live without progress notifications.

I copied the CopyFile source into my project to try debug and see what the problem is. The crashing line is the native call into copyfile_set_state.

public void SetStatusCallback(ProgressCallback callback){    this.callback = callback;    if (!gch.IsAllocated)        gch = GCHandle.Alloc(this);    copyfile_state_set(handle, Option.StatusCB, Callback); // crash    IntPtr h = GCHandle.ToIntPtr(gch);    copyfile_state_set(handle, Option.StatusCtx, ref h);}

That is defined as follows:

using copy_file_state_t = System.IntPtr;delegate NextStep RawProgressCallback(int what, int stage, IntPtr state, IntPtr str, IntPtr dst, IntPtr ctx);[DllImport("libc")]extern static int copyfile_state_set(copy_file_state_t s, Option flag, RawProgressCallback callback);

The only feedback I get is The program '[62659] CardIngestor.Daemon.dll' has exited with code 0 (0x0). I've never seen a dotnet app crash in this manner. The return code 0 tells me it isn't even a normal "crash" but something is making this happen. But I also haven't worked much with interop, especially on Mac.

I'm using .NET 6.0.100, MacOS 12.0.1 on an M1 chip. My project is on Github here: https://github.com/biltongza/CardIngestor

Does anyone have any ideas why this would be happening?


Viewing all articles
Browse latest Browse all 7190

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>