Should I use a CriticalSection on WriteFile calls?

Posted on 2010-11-08
Last Modified: 2013-12-27
I have an application in Windows CE that creates multiple threads that can at any time make a call to a log function that uses a WriteFile call. Should I use a CriticalSection around the WriteFile call and/or all the internals of the api that uses the WriteFile function or does WriteFile handle the proper sequence when multiple threads call it?

Question by:atomicgs12
LVL 86

Accepted Solution

jkr earned 167 total points
ID: 34086599
>>does WriteFile handle the proper sequence when multiple threads call it?

In simple words: Since all Windows APIs are reentrant, it is safe to assume that this one is, too. You have to take care of synchronizing access to a file yourself, so a critical section is actually a good solution.
LVL 31

Assisted Solution

Frosty555 earned 166 total points
ID: 34086658
I would not count on WriteFile handling race conditions for you. Assuming you have opened the file for writing once in your application, and all of your threads reference the same shared file handler, then yes you need a critical section.

If you have each thread independently creating new file handles with OpenFile() each time they want to write to the logfile, then the situation is slightly different. In this case, when one thread opens the file it will lock it for writing. If another thread  tries to open the same file it will fail with an "access denied" error because the file is in use. Critical sections will also help fix this, but proper error handling in the event of not being able to open the file for any reason (not enough disk space, file doesn't exist, hanging file handler from an old process etc.) is still necessary.


Assisted Solution

JimBeveridge earned 167 total points
ID: 34086985
Calling WriteFile() from multiple threads isn't going to crash Windows (or even crash your process), but there's no guarantee that data will be written in the desired order, or whether a particular data block will be written atomically. So you can end up with a mess.

Opening a file handle when your app starts and then writing from different threads using critical sections is a fine solution. The only downside is that you may need to flush the data after each write so that no data wil be lost if your app crashes.

If you open and close the file for each write to the log, Frosty555 is correct that you can rely on file sharing to prevent you from accessing the file, but there's no way to be automatically notified when the file becomes available. The only solution is to continually retry opening the file and sleep between each attempt. Not a great solution unless it's just debug code. Far better to use a critical section.

Alternatives for logging that avoid contention problems:
- Make each thread write to a separate file where each new entry has a timestamp, then merge the files later.
- Create a dedicated thread for logging and that thread is the only thread that writes to the file. Bump its priority to make sure it runs often enough. You can send data to it using a FIFO queue protected with a critical section.

Author Comment

ID: 34087321
These are all good answers. I never know how to give out points. jkr was first with an answer but Frosty555 and JimDeveridge both gave additional useable commnets. What do you guys suggest?

Expert Comment

ID: 34087335
You can split the points as you see fit. You don't have to award all of the points to one person.

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now