Reputation: 121
I have a C# .NET 6 console application that use many threads (let's say 15-30) with a shared logger instance. After many hours of work (one day or more) logged strings become corrupted as:
[2024-11-25 09:56:28:569][T:G-D][Pid:6288][Th:Thread ID = 76][Lib:**********.L1DataLoaderBeckhoffPlugin.PLCConsumerQueueManager][Ver:1.1.2]Record RotationTransRecord management completedB Closi�
Related code is:
_logger.LogDebug("Record {0} management completed", _info.recordName);
where _info.recordName
is a string that should not change after the startup and _logger
is an ILogger<...>
instance from Microsoft.Extensions.Logging
that wraps NLog
.
Corruption also occurs on fixed strings, as:
_logger.LogDebug("Program completed");
When the issue appears, almost all of the next logged strings are corrupted (from different threads too). After a while (even hours) an exception is thrown:
An error occurred while writing to logger(s). (Input string was not in a correct format.)
Input string was not in a correct format.
[2024-11-25 09:56:28:582][T:CE-M][Pid:6288][Th:Thread ID = 76][Lib:**********.P4MTechnologicalPlugin.P4MTechnologicalPlugin][Ver:1.1.2]{0} An error occurred while writing to logger(s). (Input string was not in a correct format.)
at Microsoft.Extensions.Logging.Logger.ThrowLoggingError(List`1 exceptions)
at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args)
at **********.L1DataLoaderBeckhoffPlugin.PLCConsumerQueueManager.CreateConsumerThread(Object obj)
at System.Threading.Thread.StartCallback()
Input string was not in a correct format.
at System.Text.ValueStringBuilder.ThrowFormatError()
at System.Text.ValueStringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
at System.String.Format(IFormatProvider provider, String format, Object[] args)
at Microsoft.Extensions.Logging.LogValuesFormatter.Format(Object[] values)
at NLog.Extensions.Logging.NLogLogger.CreateLogEventInfo[TState](LogLevel nLogLogLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
at NLog.Extensions.Logging.NLogLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|14_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func`3 formatter, List`1& exceptions, TState& state)
For sure the pattern format is correct in the code, and the same log has been used many times before the exception. In the application there is no explicitly unsafe code (at least in my modules). The only doubt is with some casts using the following code:
public static T CastTo<T>(this byte[] bytes) where T : struct
{
ArgumentNullException.ThrowIfNull(bytes);
if (bytes.Length != Marshal.SizeOf<T>())
throw new ArgumentException($"{nameof(bytes)}.{nameof(bytes.Length)} != {nameof(Marshal)}.{nameof(Marshal.SizeOf)}<{typeof(T).FullName}>()");
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
}
finally
{
handle.Free();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SetProgramRecoverabilityStatusRequest
{
public long programId;
public uint counter;
public uint status;
}
// Usage
byte[] data;
SetProgramRecoverabilityStatusRequest requestData;
//... data is set here
requestData = CastTo<SetProgramRecoverabilityStatusRequest>(data);
I've never got an exception from CastTo
, so I suppose there's no memory corruption here.
Do you have any idea where the problem could born and how to debug/fix it?
Thanks so much.
Upvotes: 1
Views: 74