Static logger class consideration - c#

I've found out some logger class and I am not so sure whether this class is really thread safe. True is that the Log method implements lock but access to class itself by multi threads will not raise problems? It consider me becase TextWriter tw is static so it means class has only one copy of tw and during each thread will access it can raise problems or not? BTW please take a look do you have any other objections here?:
public static class Logger
{
static readonly TextWriter tw;
private static readonly object _syncObject = new object();
static Logger(string SPath)
{
tw = TextWriter.Synchronized(File.AppendText(SPath + "\\Log.txt"));
}
public static void Write(string logMessage)
{
try
{
Log(logMessage, tw);
}
catch (IOException e)
{
tw.Close();
}
}
public static void Log(string logMessage, TextWriter w) {
// only one thread can own this lock, so other threads
// entering this method will wait here until lock is
// available.
lock(_syncObject) {
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
w.WriteLine(" :");
w.WriteLine(" :{0}", logMessage);
w.WriteLine("-------------------------------");
// Update the underlying file.
w.Flush();
}
}
}
Second version for further dicsuss purposes:
public static class Logger
{
static StreamWriter sw;
private static readonly object _syncObject = new object();
static Logger(string SPath)
{
lock(_syncObject)
{
StreamWriter sw = File.AppendText(SPath));
}
}
....

It is thread safe because every path uses the Log static method which uses a lock on the static _syncObject. This means that every thread that attempts to Log(..) will block if somebody else is logging.
However, if you call the Log method directly rather than the Write method, and you pass in a TextWriter that is being used by other threads, then that's not safe.

First of all, TextWriter is an abstract class, so the real instance might be any derived class. The documentation on TextWriter doesn't guarantee thread-safety of TextWriter implementation:
Any instance members are not guaranteed to be thread safe.
There is no guarantee that external lock will bring the thread-safety. For example, the implementation may use thread-local storage for its internal data. TextWriter.Flush may or may not help, depending on the implementation (but you never know which implementation comes into Log method and whether this implementation was e. g. created under the same lock).
This all is about Log method.
The usage of Write, on the contrary, seems to be good: it uses TextWriter.Synchronized, which is thread-safe, according to the documentation:
Creates a thread-safe wrapper around the specified TextWriter.
But take into account, that thread-safety of the synchronized text writer may or may not be the thread safety you need: if you are making to consecutive calls to Log, the results are not guaranteed to be consecutive in the output file.

Related

When is StreamWriter disposed?

I have a small class I threw together to implement a quick logger. I composed it with a private System.IO.StreamWriter which is instantiated in the constructor. Because the way I'm using is prevents me from implementing a using block, I added a finalizer and called the StreamWriter's Dispose() method in it. However, when executing, that finalizer throws an exception because the StreamWriter has already been disposed.
System.ObjectDisposedException - Cannot access a closed file.
I'm confused how this happened and I'm wondering if this means I don't need to worry about cleaning up the StreamWriter. Here is my class:
public class TextFileLogger : AbstractTextLogger
{
private const string LogPath = #"C:\";
private const string LogFileName = "MyFile.log.txt";
private readonly StreamWriter _writer;
public TextFileLogger()
{
_writer = new StreamWriter($"{LogPath}{LogFileName}", true);
_writer.AutoFlush = true;
}
~TextFileLogger()
{
_writer.Dispose();
}
protected override void WriteLine(string line)
{
_writer.WriteLine(line);
}
}
The only things you are allowed to access in a finalizer are objects that are rooted (like static variables) or objects that derive from CriticalFinalizerObject.
The problem is the finalizer is not deterministic, it is allowed to run in any order it feels like. The problem you ran in to is because the text writer was finalized before your class.
You need to either just "hope for the best" and let the writer's finalizer to do the work or you need to refactor your code so your class is disposeable itself and that calls the stream writer's dispose method.

Concurrency with reading but locking with mutating

I'm looking for a solution that allows multiple threads to read the shared resource (concurrency permitted) but then locks these reading threads once a thread enters a mutating block, to achieve best of both world.
I've looked up this reference but it seems the solution is to lock both reading and writing threads.
class Foo {
List<string> sharedResource;
public void reading() // multiple reading threads allowed, concurrency ok, lock this only if a thread enters the mutating block below.
{
}
public void mutating() // this should lock any threads entering this block as well as lock the reading threads above
{
lock(this)
{
}
}
}
Is there such a solution in C#?
Edit
All threads entering in both GetMultiton and constructor should return the same instance. want them to be thread safe.
class Foo: IFoo {
public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
{
if (instances.TryGetValue(key, out IFoo obj))
{
return obj;
}
return fooRef();
}
public Foo(string key) {
instances.Add(key, this);
}
}
protected static readonly IDictionary<string, IFoo> instances = new ConcurrentDictionary<string, IFoo>();
Use
Foo.GetMultiton("key1", () => new Foo("key1"));
There is a pre-built class for this behavior ReaderWriterLockSlim
class Foo {
List<string> sharedResource;
ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void reading() // multiple reading threads allowed, concurrency ok, lock this only if a thread enters the mutating block below.
{
_lock.EnterReadLock();
try
{
//Do reading stuff here.
}
finally
{
_lock.ExitReadLock();
}
}
public void mutating() // this should lock any threads entering this block as well as lock the reading threads above
{
_lock.EnterWriteLock();
try
{
//Do writing stuff here.
}
finally
{
_lock.ExitWriteLock();
}
}
}
Multiple threads can enter the read lock at the same time but if a write lock tries to be taken it will block till all current readers finish then block all new writers and new readers till the write lock finishes.
With your update you don't need locks at all. Just use GetOrAdd from ConcurrentDictionary
class Foo: IFoo {
public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
{
return instances.GetOrAdd(key, k=> fooRef());
}
public Foo(string key) {
instances.Add(key, this);
}
}
Note that fooRef() may be called more than once, but only the first one to return will be used as the result for all the threads. If you want fooRef() to only be called once it will require slightly more complicated code.
class Foo: IFoo {
public static IFoo GetMultiton(string key, Func<IFoo> fooRef)
{
return instances.GetOrAdd(key, k=> new Lazy<IFoo>(fooRef)).Value;
}
public Foo(string key) {
instances.Add(key, new Lazy<IFoo>(()=>this);
}
}
protected static readonly IDictionary<string, Lazy<IFoo>> instances = new ConcurrentDictionary<string, Lazy<IFoo>>();
The solution depends on your requirements. If performance of ReaderWriterLockSlim (note that it's approximately twice slower than regular lock in current .NET Framework, so maximum performance you can achieve if you modify rarely and reading is quite heavy operation, otherwise overhead will be more than profit), you can try to create copy of data, modify it and atomically swap reference with help of Interlocked class (if it's not a requirement to have the most recent data in each thread as soon as it was changed).
class Foo
{
IReadOnlyList<string> sharedResource = new List<string>();
public void reading()
{
// Here you can safely* read from sharedResource
}
public void mutating()
{
var copyOfData = new List<string>(sharedResource);
// modify copyOfData here
// Following line is correct only in case of single writer:
Interlocked.Exchange(ref sharedResource, copyOfData);
}
}
Benefits of lock-free case:
We have no locks on read, so we get maximum performance.
Drawbacks:
We have to copy data => memory traffic (allocations, garbage collection)
Reader thread can observe not the most recent update (if it reads reference before it was updated)
If reader uses sharedResource reference multiple times, then we must copy this reference to local variable via Interlocked.Exchange (if this usages of reference assume that it's the same collection)
If sharedResource is a list of mutable objects, then we must be careful with updating this objects in mutating since reader might be using them at the same moment => in this case it's better to make copies of these objects as well
If there are several updater threads, then we must use Interlocked.CompareExchange instead of Interlocked.Exchange in mutating and a kind of a loop
So, if you want to go lock-free, then it's better to use immutable objects. And anyway you will pay with memory allocations/GC for the performance.
UPDATE
Here is version that allows multiple writers as well:
class Foo
{
IReadOnlyList<string> sharedResource = new List<string>();
public void reading()
{
// Here you can safely* read from sharedResource
}
public void mutating()
{
IReadOnlyList<string> referenceToCollectionForCopying;
List<string> copyOfData;
do
{
referenceToCollectionForCopying = Volatile.Read(ref sharedResource);
copyOfData = new List<string>(referenceToCollectionForCopying);
// modify copyOfData here
} while (!ReferenceEquals(Interlocked.CompareExchange(ref sharedResource, copyOfData,
referenceToCollectionForCopying), referenceToCollectionForCopying));
}
}

Are these private static members thread safe?

I have the following code with private static members.
All of these classes say that they are thread safe in the MSDN library for "public static" members.
My question is whether these members will be thread safe when used as private static instead of "public static" as stated in the MSDN library.
public static class passwordManager
{
private static System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
private static System.Text.Encoding enc = System.Text.Encoding.ASCII;
public static string produceSalt(int size)
{
byte[] by = new byte[size];
lock (rand)
{
rand.GetBytes(by);
}
return enc.GetString(by, 0, by.Length);
}
public static string encryptPassword(string password, string salt){
return enc.GetString(shaM.ComputeHash(enc.GetBytes(password + salt)));
}
public static bool isCorrectPassword(string inputPassword, string DBsalt, string DBpassword)
{
return encryptPassword(inputPassword, DBsalt) == DBpassword;
}
This might be entirely dependent on whether the methods I am using themselves use shared variables instead of all method instance variables... some peace of mind would be helpful but I would rather not have to lock everything here if it isn't necessary.
The only reason I locked the random number generator is to limit the possibility of getting the same salt however the chances of this being called by two threads at the same time is very low in my situation.
Thanks,
Mike
This should now be thread safe. I was trying to save on object instantiation overhead but I guess there is a trade off between this and lock waiting. On a high load system lock waiting would likely greatly overpower instantiation overhead and memory usage.
public static class passwordManager
{
private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
public static byte[] produceSalt(int size)
{
byte[] by = new byte[size];
lock (rand)
{
rand.GetBytes(by);
}
return by;
}
public static byte[] encryptPassword(string password, byte[] salt){
System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
System.Text.Encoding enc = new System.Text.UTF8Encoding();
return shaM.ComputeHash(concatArrays(enc.GetBytes(password), salt));
}
public static bool isCorrectPassword(string inputPassword, byte[] DBsalt, byte[] DBpassword)
{
return compare(encryptPassword(inputPassword, DBsalt), DBpassword);
}
}
Your code is not thread-safe.
Consider the System.Text.Encoding variable enc. You are calling GetString which is an instance member. The documentation says that only public static members are thread-safe so by inference GetString is not thread-safe because it is not a public static member.1
This code may fail due to the following reasons:
You have made no attempt to synchronize access to Encoding.GetString.
Encoding.GetString is called from a public static method in your passwordManager class.
Public static methods have a high probability of being executed by multiple threads simultaneously.
The reason why public static methods are almost always designed to be thread-safe is because it would be awkward for the caller to always synchronize access to it. You cannot limit multithreaded access to static members like you can with instance members. Consider an ASP.NET application, for example. Web page requests are frequently handled concurrently on separate threads. Do you want to use a lock everytime you call a static method? Of course not. This is a ridiculous burden to place on a developer.
Update:
Your new code is now thread-safe. You will have to do some benchmark tests to see which way is faster: using a lock or instantiating new instances on every call like you have now. I would not be surprised if the lock were faster.
1The same could be said for shaM.ComputeHash and enc.GetBytes.
thread safety won't depend on whether something is private or public.
BTW, thread safety document says any public static members of this type, not when this type is embedded as public static.
In short you have to lock your fields like sham, if you are multi-threading.
You might be better off creating method level variables instead of trying to make synchronise access to shared private fields. That way you will still achieve concurrency as each thread has it's own call stack so will have separate instances of each object and thus allow multiple threads to execute the method simultaneously. If you lock on a shared object then only one thread can execute the method at a time. Another option may be to use the [ThreadStatic] attribute on each field so they will not be shared across threads.

What is the best design to this class?

assume this class:
public class Logger
{
static TextWriter fs = null;
public Logger(string path)
{
fs = File.CreateText(path);
}
public static void Log(Exception ex)
{
///do logging
}
public static void Log(string text)
{
///do logging
}
}
and I have to use this like:
Logger log = new Logger(path);
and then use Logger.Log() to log what I want. I just use one Logger.
the question is: is this a good design? to instantiate a class and then always call it's static method? any suggestion yield in better design is appreciated.
Edit based on Marc's answer:
I flush on the last line of Log and there is no need for me to read the file while it is open, the issue with file not cleanly closed is right. this class simply satisfy my requirements and there is no need to be thread safe for it. I just want to get read of the instantiation part, I should get into the SetPath you said, any suggestion for closing file?
Yes, having a constructor just for this is bad design. A static SetPath method that can only be called once (else throws an exception) would seem better. You would set the path during app-startup, etc.
Then you can either make it a static class, or a singleton if it is required to satisfy some interface-based scenario.
Next: you must add synchronisation here! That is not thread safe. If two threads attempt to log at the same time, I would expect this to collapse horribly. It doesn't need to be complex; at the simplest:
private readonly object syncLock = new object();
public static void Log(string value) {
lock(syncLock) {
//...
}
}
(but note that this may incur some blocking costs; which can be improved with more sophisticated code - see below)
There are existing logging libraries that will think of lots more issues - file partitioning, async (to stop your code being blocked by IO), batching, etc; why not just use one of them? In particular, at te moment your file will not be cleanly closed at app-exit, doesn't flush regularly, and will keep the file locked most of the time. Not good.
No, this doesn't make sense. Each time a Logger is instantiated, the static TextWriter will be overwritten, which will affect all consumers of the class. If you want to keep the instance constructor then you should make the TextWriter an instance field and the methods should be instance methods.
As an alternative, you may want to consider using log4net, which will do this kind of logging work for you.
I think you should make whole class static with static property allowing you to set up the log path.
public static class Logger
{
static TextWriter fs = null;
public static string FileName
{
set
{
fs = File.CreateText(value);
}
}
public static void Log(Exception ex)
{
if(fs == null) return;
///do logging
}
public static void Log(string text)
{
if(fs == null) return;
///do logging
}
}

Lock() in a static method

I have a multi threaded application that writes to a settings xml file using a static method. I want to avoid that the file is being updated twice at the same time (causing accesss/write exception).
How do I do that?
This doesn't work:
namespace Program
{
public class Settings
{
private static void SetSettingsValue (string settings, string value)
{
// make this thread safe to avoid writing to a locked settings xml file
lock (typeof(Settings))
{
//write data to xml file
}
}
}
}
You should create a separate, static lock object and use that. DO NOT USE A STRING! Strings are automatically interned and there will be only one instance of each programmatically declared string so you can't guarantee exclusive access to the lock.
You should do this:
public class A {
private static Object LOCK = new Object();
private static void foo() {
lock(LOCK) {
// Do whatever
}
}
}
(The syntax may be incorrect; I'm a Java person mostly but the same rules about locking and String interning apply to C#)
The lock keyword enforces a mutual exclusion lock: only one thread can lock any particular object at a time. If a second thread calls foo then it will block until the first thread has exited the lock block.
Take home messages: for a static method lock on a private static variable. Don't lock on Strings or typeof(...) because you cannot guarantee that no-one else is using that object. Always lock on an object you know is not touched by anyone else by making it private and making it new.
The concept of lock() is to use an existing-object it can reference and use to control whether access is granted.
static object SpinLock = new object();
lock(SpinLock)
{
//Statements
}
When the execution leaves the lock() block the reference is released and any other threads waiting to execute the code block can proceed (one at a time, of course).

Categories

Resources