IBuildingConfig: modding empty methods crashes mac and linux (works on windows)


Nightinggale
  • Branch: Live Branch Version: OSX Pending

I found a way to make working windows mods, which crashes on mac and linux. Even worse it's fairly easy to do so and you have no indication of it when testing on windows. I had no idea about this until lots of people reported my mod to be crashing.

It's a problem with the execution of IBuildingConfig. Take for instance EthanolDistilleryConfig. It has DoPostConfigurePreview, DoPostConfigureUnderConstruction and DoPostConfigureComplete. Adding a Postfix to all 3 works on windows, but the first two will cause a NULL exception on mac and linux, apparently because the methods are empty. My guess is that there is some sort of optimization going on, which prevents replacing an empty virtual method with another virtual method.

There is a related issue, which also affects windows. If one of the virtual methods isn't mentioned by the building and you patch it, the building will work because you end up patching IBuildingConfig. The problem here is that your newly created building will work, but your change will also apply to all other buildings not mentioning the method in question.

Solution:

I think both problems can be solved by not using virtual methods. Make them abstract instead and fill out buildings with empty methods as needed. That will force the compiler to make code for each method in each class even if those methods doesn't contain any code. At least I hope so. I have no way of testing this.

I hope to see a fix for this soon. Right now Piped Output is broken on mac and linux.


Steps to Reproduce
Mod certain IBuildingConfig methods. Verify the mod to work on windows, release and watch reports of crashes on mac and linux.
  • Sad 3


User Feedback


I believe this issue is an issue on Mono's end, because it doesn't work the same for methods with no IL body.  Some relevant GitHub issues on Harmony are an example of the bug and that Harmony only can patch methods with an IL body  Odds are that since the method is *declared* but is empty, Harmony attempts to patch it, which works on Windows, but Mono for Mac/Unix doesn't act the same way.

A potential fix is to make sure that all methods have at least a `return` or some other contents in the body?  I am not certain if the compiler would optimize that out though.

Share this comment


Link to comment
Share on other sites

Actually, what I said above is incorrect.  The method is NOT empty, it contains a single byte `ret`.  Upon further investigation, the issue is narrowed down to this method in Harmony, which has comments saying that it's hacky and can fail on some platforms.  Someone with a lot of knowledge of C# internals would need to fix this in Harmony.  I think the issue is still related to method size, like Mono doesn't like to modify a region in memory less than a certain size, related to the funlockfile in the logs, but that is just a guess.

 

In the meantime, most buildings that don't have a DoPostConfigureComplete DO use a ConfigureBuildingTemplate that can normally be used for things like adding or modifying components.

Edited by asquared31415

Share this comment


Link to comment
Share on other sites
Quote

The problem here is that your newly created building will work, but your change will also apply to all other buildings not mentioning the method in question.

I had this affect my mods as well. Now I finally know why that happend. It might be possible to work around that issue by directly injecting the affected functions into BuildingConfigManager, but that is really messy and probably not compatibility friendly.

Share this comment


Link to comment
Share on other sites


Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now