views:

624

answers:

3

We build complicated console-based tools that produce a lot of commentary on the console. These tools process a lot of data and so runs are expensive and we don't like to do them more often than necessary, especially during testing where we already have to run them repeatedly. During such tests, we often log the result to a file to capture this commentary for inspection: C:> [ourcommand] >log.txt When the application runs to completion, this works great.

If the application crashes (illegal memory reference, etc.), Windows nastily chops off the log file before the tail end of the commentary so we can't see what was occuring at the point of the crash. It also chops of the console output at the same place. So, when we get an truncated log file, we have to do it all again without the log file, to see the final answer. Windows doesn't seem to buffer the console output if not logging.

Is there a way to tell Windows not to buffer the console output while logging? Our application does use the (Windows) C runtime system and awhile back we used "setvbuf" as follows: setvbuf(stdout, NULL, _IONBF, 0); but to no avail.

+2  A: 

You can flush the console's buffer at any point:

Console.Out.Flush();

This uses TextWriter.Flush().

If you need to make sure this always happens, it'd be fairly easy to write a method for console that worked like WriteLine but included a flush statement at the end.


Edit:

You didn't specify a language... I'm going to write an example using C#.

In C#, you could easily make a static utility class that provided a method like:

public static class FlushingConsole {
    public static void WriteLine(string format, params Object[] args) {
        Console.WriteLine(format, args);
        Console.Out.Flush();
    }
    // Add other overloads as required
}

Then just call:

FlushingConsole.WriteLine(....);

The same approach should work in pretty much any other language, as well.


Edit 2:

Since you're using C++, there are a couple of options other than setvbuf that may be of interest.

First, you should be able to turn off the buffering in cout by doing:

cout.unsetf(ios_base::unitbuf);

You also may need to set sync_with_stdio if you're mixing stdio (ie: printf) with iostreams.

Reed Copsey
That's Java, I think, but there's probably a C equivelent. In any case, that assumes we know to flush the buffer before a crash. I don't know anybody with that kind of clairvoyance; we sure don't have it. Putting Flushes every is painful (these are million line programs) and so isn't an effective solution.
Ira Baxter
Meant to say, "putting flushes everywhere is painful" ...
Ira Baxter
Ira: This was for .NET (the reference is C#/.NET) What language are you using? In C#, you could do this easily with an extension method, as I said, which prevents needing the flush. I'll edit to display.
Reed Copsey
Didn't make it clear in my first post that we are using C/C++ and ASM. (Application is 13+ years old and counting... started before Java or C# existed!)
Ira Baxter
What method(s) are you using for your console output? Are you just using printf to stdout? Are you using cout << ?
Reed Copsey
@Ira Baxter: Added a couple of other things to try, depending on how your output is written. The unsetf flag may be all you need, if you're using iostreams.
Reed Copsey
I'll have to check. I'd guess it likely that there is mixed printf,cout<<, with but based on quick inspectiong the bulk likely goes through (layers of goo terminating in) putwchar, so it is likely the putwchar operations that are getting buffered.
Ira Baxter
@Ira: In that case, I'd recommend settting sync_with_stdio, call setvbuf, and do cout.unsetf. The setvbuf should handle the basic portions, but depending on the mix, you may need all 3 calls.
Reed Copsey
I won't be able to check out the effectiveness for awhile, but in terms of providing apparantly helpful directions I'm giving this answer the nod.
Ira Baxter
A: 

You didn't specify language, but for C++ you should be able to call setvbuf with stdout as the first param to turn off buffering.

Michael
We used that (thanks for reminding me of the buffering signal I mentioned above; I just went an looked at the code to verify its presence). Doesn't help.
Ira Baxter
That's very odd, it should work. You should have the CRT source code - I would step through and verify that no buffering really occurs here.
Michael
See detailed call to setvbuf (edited into my original question); perhaps something funny about how it got called? I'll look into the CRT code to see what I can learn.
Ira Baxter
A: 

You are seemingly using standard output. You'd better use "standard error". (stderr in C library, cerr in iostreams) Those are not buffered. Or you can use FlushFileBuffers (or analog), each time you wish to sync.

EFraim
Yes, we are using standard output. Umm, the output commentary isn't really error output, and these are very large applications; retrofitting all the output as stderr would not be our first choice. Yes, I know, I want the problem fixed but I don't want to do anything :-{ I'd be happy with a one time buffer-disabling call such as setvbuf if it actually worked.
Ira Baxter