Merge pull request #92 from komsa-ag/Feature/NoLock
diff --git a/.gitignore b/.gitignore
index e260d61..ad029ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -243,3 +243,4 @@
vs_buildtools.exe
dotnetfx35.exe
*.exe
+/src/Binaries/*
diff --git a/src/log4net/Appender/RemoteSyslogAppender.cs b/src/log4net/Appender/RemoteSyslogAppender.cs
index 675d6f9..b67abd3 100644
--- a/src/log4net/Appender/RemoteSyslogAppender.cs
+++ b/src/log4net/Appender/RemoteSyslogAppender.cs
@@ -344,88 +344,98 @@
/// </remarks>
protected override void Append(LoggingEvent loggingEvent)
{
- try
- {
- // Priority
- int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
+ try
+ {
+ // Priority
+ int priority = GeneratePriority(m_facility, GetSeverity(loggingEvent.Level));
- // Identity
- string identity;
+ // Identity
+ string identity;
- if (m_identity != null)
- {
- identity = m_identity.Format(loggingEvent);
- }
- else
- {
- identity = loggingEvent.Domain;
- }
+ if (m_identity != null)
+ {
+ identity = m_identity.Format(loggingEvent);
+ }
+ else
+ {
+ identity = loggingEvent.Domain;
+ }
- // Message. The message goes after the tag/identity
- string message = RenderLoggingEvent(loggingEvent);
+ // Message. The message goes after the tag/identity
+ string message = RenderLoggingEvent(loggingEvent);
- Byte[] buffer;
- int i = 0;
- char c;
+ byte[] buffer;
+ int i = 0;
- StringBuilder builder = new StringBuilder();
+ StringBuilder builder = new StringBuilder();
- while (i < message.Length)
- {
- // Clear StringBuilder
- builder.Length = 0;
+ while (i < message.Length)
+ {
+ // Clear StringBuilder
+ builder.Length = 0;
- // Write priority
- builder.Append('<');
- builder.Append(priority);
- builder.Append('>');
+ // Write priority
+ builder.Append('<');
+ builder.Append(priority);
+ builder.Append('>');
- // Write identity
- builder.Append(identity);
- builder.Append(": ");
+ // Write identity
+ builder.Append(identity);
+ builder.Append(": ");
- for (; i < message.Length; i++)
- {
- c = message[i];
+ AppendMessage(message, ref i, builder);
- // Accept only visible ASCII characters and space. See RFC 3164 section 4.1.3
- if (((int)c >= 32) && ((int)c <= 126))
- {
- builder.Append(c);
- }
- // If character is newline, break and send the current line
- else if ((c == '\r') || (c == '\n'))
- {
- // Check the next character to handle \r\n or \n\r
- if ((message.Length > i + 1) && ((message[i + 1] == '\r') || (message[i + 1] == '\n')))
- {
- i++;
- }
- i++;
- break;
- }
- }
-
- // Grab as a byte array
- buffer = this.Encoding.GetBytes(builder.ToString());
+ // Grab as a byte array
+ buffer = this.Encoding.GetBytes(builder.ToString());
#if NET_4_5 || NETSTANDARD
- Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait();
+ Client.SendAsync(buffer, buffer.Length, RemoteEndPoint).Wait();
#else
- this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
+ this.Client.Send(buffer, buffer.Length, this.RemoteEndPoint);
#endif
- }
- }
- catch (Exception e)
- {
- ErrorHandler.Error(
- "Unable to send logging event to remote syslog " +
- this.RemoteAddress.ToString() +
- " on port " +
- this.RemotePort + ".",
- e,
- ErrorCode.WriteFailure);
- }
+ }
+ }
+ catch (Exception e)
+ {
+ ErrorHandler.Error(
+ "Unable to send logging event to remote syslog " +
+ this.RemoteAddress.ToString() +
+ " on port " +
+ this.RemotePort + ".",
+ e,
+ ErrorCode.WriteFailure);
+ }
+ }
+
+ /// <summary>
+ /// Appends the rendered message to the buffer
+ /// </summary>
+ /// <param name="message">rendered message</param>
+ /// <param name="characterIndex">index of the current character in the message</param>
+ /// <param name="builder">buffer</param>
+ protected virtual void AppendMessage(string message, ref int characterIndex, StringBuilder builder)
+ {
+ for (; characterIndex < message.Length; characterIndex++)
+ {
+ char c = message[characterIndex];
+
+ // Accept only visible ASCII characters and space. See RFC 3164 section 4.1.3
+ if (((int)c >= 32) && ((int)c <= 126))
+ {
+ builder.Append(c);
+ }
+ // If character is newline, break and send the current line
+ else if ((c == '\r') || (c == '\n'))
+ {
+ // Check the next character to handle \r\n or \n\r
+ if ((message.Length > characterIndex + 1) && ((message[characterIndex + 1] == '\r') || (message[characterIndex + 1] == '\n')))
+ {
+ characterIndex++;
+ }
+ characterIndex++;
+ break;
+ }
+ }
}
/// <summary>
diff --git a/src/log4net/Util/SystemInfo.cs b/src/log4net/Util/SystemInfo.cs
index 92e2c60..821a230 100644
--- a/src/log4net/Util/SystemInfo.cs
+++ b/src/log4net/Util/SystemInfo.cs
@@ -59,7 +59,7 @@
/// Only static methods are exposed from this type.
/// </para>
/// </remarks>
- private SystemInfo()
+ private SystemInfo()
{
}
@@ -142,7 +142,7 @@
/// </remarks>
public static string ApplicationBaseDirectory
{
- get
+ get
{
#if NETCF
- return System.IO.Path.GetDirectoryName(SystemInfo.EntryAssemblyLocation) + System.IO.Path.DirectorySeparatorChar;
@@ -170,7 +170,7 @@
/// </remarks>
public static string ConfigurationFileLocation
{
- get
+ get
{
#if NETCF || NETSTANDARD
return SystemInfo.EntryAssemblyLocation+".config";
@@ -180,6 +180,8 @@
}
}
+ private static string entryAssemblyLocation;
+
/// <summary>
/// Gets the path to the file that first executed in the current <see cref="AppDomain"/>.
/// </summary>
@@ -191,16 +193,20 @@
/// </remarks>
public static string EntryAssemblyLocation
{
- get
+ get
{
+ if (entryAssemblyLocation != null)
+ return entryAssemblyLocation;
#if NETCF
- return SystemInfo.NativeEntryAssemblyLocation;
+ return entryAssemblyLocation = SystemInfo.NativeEntryAssemblyLocation;
#elif NETSTANDARD1_3 // TODO GetEntryAssembly is available for netstandard1.5
- return AppContext.BaseDirectory;
+ return entryAssemblyLocation = AppContext.BaseDirectory;
#else
- return System.Reflection.Assembly.GetEntryAssembly().Location;
+ return entryAssemblyLocation = Assembly.GetEntryAssembly()?.Location
+ ?? throw new InvalidOperationException($"Unable to determine EntryAssembly location: EntryAssembly is null. Try explicitly setting {nameof(SystemInfo)}.{nameof(EntryAssemblyLocation)}");
#endif
}
+ set => entryAssemblyLocation = value;
}
/// <summary>
@@ -227,7 +233,7 @@
/// </remarks>
public static int CurrentThreadId
{
- get
+ get
{
#if NETCF_1_0
return System.Threading.Thread.CurrentThread.GetHashCode();
@@ -295,10 +301,10 @@
s_hostName = Environment.MachineName;
#endif
}
- catch(InvalidOperationException)
+ catch (InvalidOperationException)
{
}
- catch(System.Security.SecurityException)
+ catch (System.Security.SecurityException)
{
// We may get a security exception looking up the machine name
// You must have Unrestricted EnvironmentPermission to access resource
@@ -343,7 +349,7 @@
s_appFriendlyName = AppDomain.CurrentDomain.FriendlyName;
#endif
}
- catch(System.Security.SecurityException)
+ catch (System.Security.SecurityException)
{
// This security exception will occur if the caller does not have
// some undefined set of SecurityPermission flags.
@@ -357,7 +363,7 @@
string assemblyLocation = SystemInfo.EntryAssemblyLocation;
s_appFriendlyName = System.IO.Path.GetFileName(assemblyLocation);
}
- catch(System.Security.SecurityException)
+ catch (System.Security.SecurityException)
{
// Caller needs path discovery permission
}
@@ -392,35 +398,35 @@
/// will be set per AppDomain.
/// </para>
/// </remarks>
- [Obsolete("Use ProcessStartTimeUtc and convert to local time if needed.")]
+ [Obsolete("Use ProcessStartTimeUtc and convert to local time if needed.")]
public static DateTime ProcessStartTime
{
get { return s_processStartTimeUtc.ToLocalTime(); }
}
- /// <summary>
- /// Get the UTC start time for the current process.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This is the UTC time at which the log4net library was loaded into the
- /// AppDomain. Due to reports of a hang in the call to <c>System.Diagnostics.Process.StartTime</c>
- /// this is not the start time for the current process.
- /// </para>
- /// <para>
- /// The log4net library should be loaded by an application early during its
- /// startup, therefore this start time should be a good approximation for
- /// the actual start time.
- /// </para>
- /// <para>
- /// Note that AppDomains may be loaded and unloaded within the
- /// same process without the process terminating, however this start time
- /// will be set per AppDomain.
- /// </para>
- /// </remarks>
- public static DateTime ProcessStartTimeUtc
- {
- get { return s_processStartTimeUtc; }
+ /// <summary>
+ /// Get the UTC start time for the current process.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// This is the UTC time at which the log4net library was loaded into the
+ /// AppDomain. Due to reports of a hang in the call to <c>System.Diagnostics.Process.StartTime</c>
+ /// this is not the start time for the current process.
+ /// </para>
+ /// <para>
+ /// The log4net library should be loaded by an application early during its
+ /// startup, therefore this start time should be a good approximation for
+ /// the actual start time.
+ /// </para>
+ /// <para>
+ /// Note that AppDomains may be loaded and unloaded within the
+ /// same process without the process terminating, however this start time
+ /// will be set per AppDomain.
+ /// </para>
+ /// </remarks>
+ public static DateTime ProcessStartTimeUtc
+ {
+ get { return s_processStartTimeUtc; }
}
/// <summary>
@@ -483,7 +489,7 @@
#if NETCF
return "Not supported on Microsoft .NET Compact Framework";
#elif NETSTANDARD1_3
- return "Not supported on .NET Core";
+ return "Not supported on .NET Core";
#else
if (myAssembly.GlobalAssemblyCache)
{
@@ -665,7 +671,7 @@
return GetTypeFromString(relativeType.Assembly, typeName, throwOnError, ignoreCase);
#endif
}
-
+
#if !NETSTANDARD1_3
/// <summary>
/// Loads the type specified in the type string.
@@ -715,7 +721,7 @@
public static Type GetTypeFromString(Assembly relativeAssembly, string typeName, bool throwOnError, bool ignoreCase)
{
// Check if the type name specifies the assembly name
- if(typeName.IndexOf(',') == -1)
+ if (typeName.IndexOf(',') == -1)
{
//LogLog.Debug(declaringType, "SystemInfo: Loading type ["+typeName+"] from assembly ["+relativeAssembly.FullName+"]");
#if NETSTANDARD1_3
@@ -737,7 +743,7 @@
{
loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
}
- catch(System.Security.SecurityException)
+ catch (System.Security.SecurityException)
{
// Insufficient permissions to get the list of loaded assemblies
}
@@ -746,33 +752,33 @@
{
Type fallback = null;
// Search the loaded assemblies for the type
- foreach (Assembly assembly in loadedAssemblies)
+ foreach (Assembly assembly in loadedAssemblies)
{
Type t = assembly.GetType(typeName, false, ignoreCase);
if (t != null)
{
// Found type in loaded assembly
- LogLog.Debug(declaringType, "Loaded type ["+typeName+"] from assembly ["+assembly.FullName+"] by searching loaded assemblies.");
- if (assembly.GlobalAssemblyCache)
- {
- fallback = t;
- }
- else
- {
- return t;
- }
+ LogLog.Debug(declaringType, "Loaded type [" + typeName + "] from assembly [" + assembly.FullName + "] by searching loaded assemblies.");
+ if (assembly.GlobalAssemblyCache)
+ {
+ fallback = t;
+ }
+ else
+ {
+ return t;
+ }
}
}
- if (fallback != null)
- {
- return fallback;
- }
+ if (fallback != null)
+ {
+ return fallback;
+ }
}
// Didn't find the type
if (throwOnError)
{
- throw new TypeLoadException("Could not load type ["+typeName+"]. Tried assembly ["+relativeAssembly.FullName+"] and all loaded assemblies");
+ throw new TypeLoadException("Could not load type [" + typeName + "]. Tried assembly [" + relativeAssembly.FullName + "] and all loaded assemblies");
}
return null;
#endif
@@ -938,20 +944,20 @@
#endif
}
- /// <summary>
- /// Parse a string into an <see cref="Int16"/> value
- /// </summary>
- /// <param name="s">the string to parse</param>
- /// <param name="val">out param where the parsed value is placed</param>
- /// <returns><c>true</c> if the string was able to be parsed into an integer</returns>
- /// <remarks>
- /// <para>
- /// Attempts to parse the string into an integer. If the string cannot
- /// be parsed then this method returns <c>false</c>. The method does not throw an exception.
- /// </para>
- /// </remarks>
- public static bool TryParse(string s, out short val)
- {
+ /// <summary>
+ /// Parse a string into an <see cref="Int16"/> value
+ /// </summary>
+ /// <param name="s">the string to parse</param>
+ /// <param name="val">out param where the parsed value is placed</param>
+ /// <returns><c>true</c> if the string was able to be parsed into an integer</returns>
+ /// <remarks>
+ /// <para>
+ /// Attempts to parse the string into an integer. If the string cannot
+ /// be parsed then this method returns <c>false</c>. The method does not throw an exception.
+ /// </para>
+ /// </remarks>
+ public static bool TryParse(string s, out short val)
+ {
#if NETCF
val = 0;
try
@@ -965,28 +971,28 @@
return false;
#else
- // Initialise out param
- val = 0;
+ // Initialise out param
+ val = 0;
- try
- {
- double doubleVal;
- if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal))
- {
- val = Convert.ToInt16(doubleVal);
- return true;
- }
- }
- catch
- {
- // Ignore exception, just return false
- }
+ try
+ {
+ double doubleVal;
+ if (Double.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out doubleVal))
+ {
+ val = Convert.ToInt16(doubleVal);
+ return true;
+ }
+ }
+ catch
+ {
+ // Ignore exception, just return false
+ }
- return false;
+ return false;
#endif
- }
+ }
- /// <summary>
+ /// <summary>
/// Lookup an application setting
/// </summary>
/// <param name="key">the application settings key to lookup</param>
@@ -1008,7 +1014,7 @@
return ConfigurationSettings.AppSettings[key];
#endif
}
- catch(Exception ex)
+ catch (Exception ex)
{
// If an exception is thrown here then it looks like the config file does not parse correctly.
LogLog.Error(declaringType, "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex);
@@ -1086,28 +1092,28 @@
#endif
}
- /// <summary>
- /// Tests two strings for equality, the ignoring case.
- /// </summary>
- /// <remarks>
- /// If the platform permits, culture information is ignored completely (ordinal comparison).
- /// The aim of this method is to provide a fast comparison that deals with <c>null</c> and ignores different casing.
- /// It is not supposed to deal with various, culture-specific habits.
- /// Use it to compare against pure ASCII constants, like keywords etc.
- /// </remarks>
- /// <param name="a">The one string.</param>
- /// <param name="b">The other string.</param>
- /// <returns><c>true</c> if the strings are equal, <c>false</c> otherwise.</returns>
- public static Boolean EqualsIgnoringCase(String a, String b)
- {
+ /// <summary>
+ /// Tests two strings for equality, the ignoring case.
+ /// </summary>
+ /// <remarks>
+ /// If the platform permits, culture information is ignored completely (ordinal comparison).
+ /// The aim of this method is to provide a fast comparison that deals with <c>null</c> and ignores different casing.
+ /// It is not supposed to deal with various, culture-specific habits.
+ /// Use it to compare against pure ASCII constants, like keywords etc.
+ /// </remarks>
+ /// <param name="a">The one string.</param>
+ /// <param name="b">The other string.</param>
+ /// <returns><c>true</c> if the strings are equal, <c>false</c> otherwise.</returns>
+ public static Boolean EqualsIgnoringCase(String a, String b)
+ {
#if NET_1_0 || NET_1_1 || NETCF_1_0
- return string.Compare(a, b, true, System.Globalization.CultureInfo.InvariantCulture) == 0
+ return string.Compare(a, b, true, System.Globalization.CultureInfo.InvariantCulture) == 0
#elif NETSTANDARD1_3
- return CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0;
+ return CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0;
#else // >= .NET-2.0
- return String.Equals(a, b, StringComparison.OrdinalIgnoreCase);
+ return String.Equals(a, b, StringComparison.OrdinalIgnoreCase);
#endif
- }
+ }
#endregion Public Static Methods
@@ -1169,14 +1175,14 @@
#region Private Static Fields
- /// <summary>
- /// The fully qualified type of the SystemInfo class.
- /// </summary>
- /// <remarks>
- /// Used by the internal logger to record the Type of the
- /// log message.
- /// </remarks>
- private static readonly Type declaringType = typeof(SystemInfo);
+ /// <summary>
+ /// The fully qualified type of the SystemInfo class.
+ /// </summary>
+ /// <remarks>
+ /// Used by the internal logger to record the Type of the
+ /// log message.
+ /// </remarks>
+ private static readonly Type declaringType = typeof(SystemInfo);
/// <summary>
/// Cache the host name for the current machine