Talk about nasty bugs

time to read 2 min | 305 words

Let us see how many of you can figure this one out.

Here is the code:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CopyFileEx(string lpExistingFileName, string lpNewFileName,
   IntPtr lpProgressRoutine, IntPtr lpData, ref Int32 pbCancel,
   CopyFileFlags dwCopyFlags);

public void CopyFileWithProgressReports()
{
    var lpProgressRoutineIntPtr = Marshal.GetFunctionPointerForDelegate(new CopyProgressRoutine(LpProgressRoutine));
    int pbCancel = 0;
    CopyFileEx(hugeFile, hugeFile + ".new", lpProgressRoutineIntPtr, IntPtr.Zero, ref pbCancel,
           CopyFileFlags.COPY_FILE_RESTARTABLE);        
}

private static CopyProgressResult LpProgressRoutine(long totalFileSize, long totalBytesTransferred, long streamSize, 
    long streamBytesTransferred, uint dwStreamNumber, CopyProgressCallbackReason dwCallbackReason, IntPtr hSourceFile, 
    IntPtr hDestinationFile, IntPtr lpData)
{
    Console.WriteLine("{0:#,#} / {1:#,#}", totalBytesTransferred, totalFileSize);
    return CopyProgressResult.PROGRESS_CONTINUE;
}

This code will run perfectly if you execute it in a single threaded fashion.

But, if you run it on a background thread and continue to do additional operations (just running it on a background thread work) that has nothing to do with the file system, it will crash, sometimes with a null reference exception, sometimes with attempt to write to protected memory, etc.

There is a very subtle bug here, can you figure out what it is?