spdlog
spdlog copied to clipboard
Logger in Unmanaged DLL called by C# DLL crashes Oracle Simphony
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.
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 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.
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 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.
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);
You also should not use periodic flush - since this also creates a thread inside spdlog
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.
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 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.
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 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.
Updating the redistributables on the clients machine fixed the issue. Thank you all again for all the help! Closing the issue.