spdlog icon indicating copy to clipboard operation
spdlog copied to clipboard

Logger in Unmanaged DLL called by C# DLL crashes Oracle Simphony

Open EthanHipps opened this issue 1 year ago • 1 comments
trafficstars

We've been using this logger for a while in our C++ code base without issue. Recently we ported the library to Windows so that we could compile it as a DLL that can be used by a C# DLL using DllImport. That C# DLL is used by Oracle Simphony for an Extensibility application.

We started getting the exception:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

We pinpointed the cause of the exception to the logger (commented out every log and the crash disappears).

We use a static class to contain the loggers (excerpts below): loggers.h:

static Loggers &get() noexcept
{
    static Loggers instance;

    return instance;
}

std::shared_ptr<spdlog::logger> debugLogger;

loggers.cpp:

int fileSize = 1024 * 1024 * 5; // 5 MB
int maxFiles = 5;
debugLogger = spdlog::create_async<spdlog::sinks::rotating_file_sink_mt>("DebugLogger", "trace.log", fileSize, maxFiles);

This is called like so: example.cpp

Loggers::get().debugLogger->debug("This is a debug log");

We have a c# test application for the unmanaged DLL that is created by the c++ code. Logging works without issue there, but as soon as we call it from Simphony we get the System.AccessViolationException. Sometimes it continues running, other times it crashes/freezes the whole application.

If I use basic_logger_mt/st the trace file is created but nothing is logged to it. If I use the asynchronous logger no file is created. Calling the static logger or just Loggers::get() also causes the crash.

I've tried multiple versions of the library (v. 1.11-1.14.1) and tried both the compiled and header only versions.

I've read a couple of the wikis and other issues about using the library in a DLL, but most of them have to do with destructing or calling the DLL from another c++ application. Is there anything that should be done that applies specifically to a unmanaged DLL that is used via DllImport in C#?

Any ideas or help would be appreciated.

EthanHipps avatar Jun 28 '24 16:06 EthanHipps

I am not familiar with C#, but I do know that you cannot call C++ functions directly. Instead of calling a C++ function in C#, you must expose a C function that wraps a C++ function. Please check similar questions on StackOverflow:

  • https://stackoverflow.com/questions/29764548/call-c-native-unmanaged-member-functions-from-c-sharp-when-member-functions-we
  • https://stackoverflow.com/questions/7872392/c-dll-and-c-sharp-call

tt4g avatar Jun 28 '24 20:06 tt4g

@tt4g Thank you for your response. We are using a wrapper class that exposes C functions for the C# code to call, similar to the example in the the first link you provided.

Just to clarify a few things from my initial post, we have two DLLs: a C++ library, and a C# library that relies on the C++ library. We are not having any issues communicating with the C++ library nor are we trying to access the logger from the C# library. The issue we're running into is that the logger causes a System.AccessViolationException in the C# library, but only when our C# library is called from Oracle Simphony. In our test app, when we call the C# library, the logger works without issue. That's why I was asking if there is a specific way I should initialize the logger, since I don't have access to a "main" to register the logger in as shown in the "How to use spdlog in DLLs wiki".

I tried your example here, https://github.com/gabime/spdlog/issues/1562#issuecomment-632011851, with no luck.

EthanHipps avatar Jun 30 '24 22:06 EthanHipps

I don't know anything about Oracle Simphony, but if it works in testing and causes problems when run on Oracle Simphony, then I should think that the cause is Oracle Simphony. Have you contacted Oracle Simphony support?

tt4g avatar Jul 01 '24 10:07 tt4g

@tt4g I've reached out to them, waiting on a response. Is there a way to log from spdlog without creating any additional worker threads? Also, if it makes any difference, Simphony runs in 32bit as does all of our code.

EthanHipps avatar Jul 01 '24 20:07 EthanHipps

Is there a way to log from spdlog without creating any additional worker threads

Yes, Don’t use async logger.

If you must use async logger, it is worth trying to create the async logger directly, with a newly created thread pool object:

auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
auto logger = std::make_shared<spdlog::async_logger>("DebugLogger", some _sink,spdlog::async_overflow_policy::block);

gabime avatar Jul 01 '24 20:07 gabime

You also should not use periodic flush - since this also creates a thread inside spdlog

artemyv avatar Jul 02 '24 05:07 artemyv

Just wanted to give all of you an update real quick. As @gabime suggested, I tried both a sync and async logger with a new thread pool, both resulted in the same error. @artemyv Thank you for the info, we are not using periodic flush, but I messed around with manually flushing and vice versa; neither made a difference.

Now what did fix the error was installing Visual Studio (minimal installation, no extras installed, only the editor). The error is gone even after uninstalling Visual Studio. Not sure what it added that fixed the error, but I'll post another update once I find out.

Thank you all again for all of your help. I really appreciate it.

EthanHipps avatar Jul 08 '24 14:07 EthanHipps

Now what did fix the error was installing Visual Studio (minimal installation, no extras installed, only the editor). The error is gone even after uninstalling Visual Studio. Not sure what it added that fixed the error, but I'll post another update once I find out.

A breaking change in Visual Studio (microsoft/STL#4730) may have been the cause.

tt4g avatar Jul 08 '24 14:07 tt4g

@tt4g Thanks for making me aware of that issue. But, I'm not sure it applies to my issue. I realize I wasn't clear in my last post. To clarify, I installed and uninstalled Visual Studio on the target machine (the one with Simphony installed on it), not my development machine. I haven't changed anything on my development machine.

EthanHipps avatar Jul 09 '24 16:07 EthanHipps

The crash that occurs with the microsoft/STL#4730 change is when the Visual Studio Runtime on the machine running the application is older than the Visual Studio on the development machine. It is possible that the runtime was updated when Visual Studio was reinstalled.

https://github.com/gabime/spdlog/issues/2902#issuecomment-2198418994

This problem does not seem to occur if the Microsoft Visual C++ 2015-2022 Redistributable package and toolset is up-to-date, even if it is Visual Studio version 17.10.0 or later.

tt4g avatar Jul 09 '24 21:07 tt4g

@tt4g Got it, thank you for further explaining it. I'm currently waiting to find out if the new runtime fixes the issue on the client's machines, but will update (and hopefully close) the issue once I find out. Thank you again for all of the help.

EthanHipps avatar Jul 09 '24 21:07 EthanHipps

Updating the redistributables on the clients machine fixed the issue. Thank you all again for all the help! Closing the issue.

EthanHipps avatar Jul 10 '24 17:07 EthanHipps