Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streamwriter Lock Not Working

I'm taking over a C# project, and when testing it out I'm getting errors. The error is that the log file cannot be written to because it is in use by another process. Here's the code:

    public void WriteToLog(string msg)
    {
        if (!_LogExists) 
        {
            this.VerifyOrCreateLogFile();  // Creates log file if it does not already exist.
        }

        // do the actual writing on its own thread so execution control can immediately return to the calling routine.
        Thread t = new Thread(new ParameterizedThreadStart(WriteToLog));
        t.Start((object)msg);
    }

    private void WriteToLog(object msg)
    {
        lock (_LogLock)
        {
            string message = msg as string;
            using (StreamWriter sw = File.AppendText(LogFile))
            {
                sw.Write(message);
                sw.Close();
            }
        }
    }

_LogLock is defined as a class variable:

    private object _LogLock = 0;

Based on my research and the fact that this has been working fine in a production system for a few years now, I don't know what the problem could be. The lock should prevent another thread from attempting to write to the log file.

The changes I've made that need to be tested are a lot more log usage. We're basically adding a debug mode to save much more info to the log than used to be saved.

Thanks for any help!

EDIT:

Thanks for the quick answers! The code for VerifyOrCreateLogFile() does use the _LogLock, so that shouldn't be an issue. It does do some writing to the log before it errors out, so it gets past creating the file just fine.

What seems to be the problem is that previously only one class created an instance of the log class, and now I've added instances to other classes. It makes sense that this would create problems. Changing the _LogLock field to be static fixes the issue.

Thanks again!

like image 479
Greg Avatar asked Dec 27 '22 14:12

Greg


2 Answers

The lock should prevent another thread from attempting to write to the log file.

This is only true if you're using a single instance of this class.

If each (or even some) of the log requests use a separate instance, then the lock will not protect you.

You can easily "correct" this by making the _LogLock field static:

private static object _LogLock = 0;

This way, all instances will share the same lock.

like image 124
Reed Copsey Avatar answered Jan 12 '23 12:01

Reed Copsey


I see 2 problems with the code:

  • Lock must be the same among all "users" of ths Log class, easiest solution is to make either _LogLock or the complete class static
  • VerifyOrCreateLogFile could pose a problem if 2 or more parallel threads call WriteToLog when _LogExists is false...
like image 25
Yahia Avatar answered Jan 12 '23 12:01

Yahia