Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by master3ath · May 24, 2016 at 01:43 AM · crashnative pluginthreadinginterop

functional multithreaded c++ code crashes if executed in Unity as native plugin

Edit: Solved. Accepted the answer because it was more useful for Unity users. However, as you may have suspected, it turns out I didn't sufficiently test my native code. In particular, after I wrote my own game module, I found a lot of chunks were being indexed inconsistently, leading to attempts to access pointers far beyond their bounds (I once accessed a chunk pointer with the world offset instead of the chunk offset, for example). There was another problem too: apparently, ERROR_ALREADY_EXISTS is different from ERROR_FILE_EXISTS so the chunk files were only being mapped if they didn't already exist.

Hi,

I have a set of routines in C++ that samples many megabytes of volumetric data from several memory-mapped files on-demand, i.e., whenever it needs to sample or modify a particular point it either generates it or loads it from a file-backed virtual memory. I expose two methods for this: GetVoxel() and SetVoxel(). Then I have another function StartWorld(), that creates a thread, which as long as the process is running updates an efficient curved bsp structure from all the voxel data, from a producer queue of chunks that need to be updated. I have a third function, Raycast(), that performs a software occlusion query or cone visibility approximation using a signed distance to the b-rep. I need to make a native plugin from them on Windows but they crash...only when invoked from Unity.

I have tested all of these in a simple C++11 console app and they work just fine, running all tests without issue on both Windows and Linux. The functions I expose to mono are extern "C" and I can verify it is running them from the dll with sane arguments. But when I try to run the plugin (call StartWorld(), then SetVoxel() a number of times, then RayCast() about 3200 times) in the editor it crashes the entire editor; a similar thing happens in the game build. I get an access violation somewhere trying to access my memory-mapped file. But here's the annoying thing: this is the exact sequence of calls I make in my C++ tests, which also use two threads and have no issues with concurrency, and my files are being created, and the pointers being returned by MapViewOfFile are valid (I logged the addresses, and it does indeed sample more than 16kb of voxel data before suddenly crashing).

What could be causing this disparity between how my code behaves in C++ and when invoked from mono in Unity?

I have this code in C#:

 using UnityEngine;
 using System.Collections;
 using System.Runtime.InteropServices;
 public class VoxelWorldManager : MonoBehaviour {
     
 
     [DllImport ("Fiefdom", EntryPoint = "GetVoxel", CallingConvention = CallingConvention.Cdecl)]
     public static extern int GetVoxel(int x, int y, int z);//this will create a new memory-mapped file view if the voxel coordinate doesn't exist. The corresponding c++ function is thread-safe.
 
     [DllImport ("Fiefdom", EntryPoint = "SetVoxel", CallingConvention = CallingConvention.Cdecl)]
     public static extern void SetVoxel(int x, int y, int z, int voxel);//this will create a new memory-mapped file view if the voxel coordinate doesn't exist. The corresponding c++ function is thread-safe.
 
     [DllImport("Fiefdom", EntryPoint = "LoadMap", CallingConvention = CallingConvention.Cdecl)]
     public static extern void LoadMap([MarshalAs(UnmanagedType.LPStr)]string filename);//this simply passes the filename to the c++ code as a parameter.  I know it works because files are being created with this name.
 
     [DllImport ("Fiefdom", EntryPoint ="StartWorld", CallingConvention= CallingConvention.Cdecl)]
     public static extern void StartWorld();//this spawns a new thread but in C++ when I use it it works.  
 
     [DllImport ("Fiefdom", EntryPoint = "Raycast", CallingConvention = CallingConvention.Cdecl)]
     private static extern void Raycast([MarshalAs(UnmanagedType.LPArray, SizeConst = 5)] int[] voxel,   float rx, float ry, float rz, float ex, float ey, float ez);//my code hasn't got as far as this yet from Unity but in C++ I can raycast as many times as I want, even while the chunks are being updated, critical sections protect from any synchronization issues.
     
 }

Plus some start and update routines, etc... Start() calls the initialization routines then sets many voxels from a heightmap; Update() does a large number of very quick raycasts only after Start() has finished. The same sequence works when I do it in native code. }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · May 24, 2016 at 12:10 PM

Are you sure you use the right calling convention? The default calling convention (UNITY_INTERFACE_API inside the IUnityInterface.h) for native plugins on windows is "stdcall" and not "cdecl". If you mess that up it will result in a crash as you mess up the stack that way. So make sure you use the correct one.

Apart from that are you sure that all your methods that are invoked from Unity are threadsafe? Concurrency problems are hard to debug and this is a typical symptom if it runs fine on one system but fails on another. If a racecondition causes a problem highly depends on the hardware / software combination and "random luck".

Another reason could be that you messed up the marshalling of the parameters. Do the method parameters use managed memory exclusively? We don't know how the interface of your DLL actually looks like.

Keep in mind that references to temporary managed variables passed to native code must not be stored on the native code side as the managed memory can't track the usage of the reference / pointer in native code. I'm thinking about the string parameter of "LoadMap" for example. You always should copy the data into some native memory if it should persist.

I understand that your library is quite complex and that you don't want / can't post the source here, but a bit more details about what happens with the parameters and how they are defined on the native side would help i guess.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

UDP with coroutines crashing unity? 1 Answer

Editor crash "allocation 0x0xc000000000000000 already registered" 0 Answers

Crash on Application.Quit() in standalone mode after closing window 1 Answer

Invoking Windows Multimedia timer results to hang 1 Answer

How to synchronize native plugin texture update with orientation change from script 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges