NVelocity: "Cannot read from a closed TextReader" - c#

Just getting started on NVelocity (v1.1.1) and it seems to be working just fine.
There's just one small thing that annoys me. I've set up VS2010 to break each time an exception is thrown even though it gets handled somewhere, and when running the following code, it always breaks at the call to Evaluate, stating that it "Cannot read from a closed TextReader" (ObjectDisposedException). I do not have the source code for NVelocity, so I cannot debug.
Am I missing a setting somewhere that causes this? Is it just a harmless bug in NVelocity? The result comes out fine, to me it just seems like something's not quite right.
var velocity = new VelocityEngine();
var properties = new ExtendedProperties();
var context = new VelocityContext(fieldValues);
properties.AddProperty("velocimacro.library", string.Empty); // no library
velocity.Init(properties);
using (var writer = new StringWriter())
{
velocity.Evaluate(context, writer, null, templateContents);
return writer.ToString();
}
Exception stack trace:
at System.IO.__Error.ReaderClosed() at
System.IO.StringReader.Read(Char[] buffer, Int32 index, Int32 count)
at NVelocity.Runtime.Parser.VelocityCharStream.FillBuff() in
c:\...\src\NVelocity\Runtime\Parser\VelocityCharStream.cs:line 313

This is a first-chance exception. You can see in the source code that this exception is caught right afterwards within NVelocity code.

Related

Socket.EndAccept throwing ArgumentException

Using .NET 6.0.
I called BeginAccept like so:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
and my AcceptCallback method gets called as expected. I then have to call EndAccept to obtain the receive socket:
private static void AcceptCallback(IAsyncResult result)
{
Socket? listenSocket = result.AsyncState as Socket;
if (listenSocket == null)
{
// note: This is impossible but it helps getting the possible
// null reference warnings out of the way.
throw new ArgumentNullException(nameof(result.AsyncState), "The state object is null.");
}
Socket receiveSocket = listenSocket.EndAccept(
out byte[] buffer,
out int bytesRead,
result); // and here it blows up
The last call gives me a "System.ArgumentException: 'Value does not fall within the expected range. (Parameter 'asyncResult')'".
Apparently is has a problem with the last argument. It is not something I provide though, it is the result argument I get passed by the system which (according to the debugger) is a proper System.Threading.Tasks.TaskToApm.TaskAsyncResult. I am just following the examples I found.
I started out without the wrapping new AsyncCallback() in the call to BeginAccept because I did not understand what good it does (I would like to know though). I also initially had non-static methods. Because I had this problem I changed it to be more like the original examples but the same exception remains.
What is the problem and what can I do to overcome it?
[Edit]
As pointed out by Hans Passant the result argument should not be a System.Threading.Tasks.TaskToApm.TaskAsyncResult and this causes the error. There is little talk or documentation about TaskAsyncResult on the internet which made me suspicious, thinking it could be a bug in new framework code. So I rebuild with .NET 5.0 but the result was the same.
I am just using System.Net.Sockets.Socket classes, nothing fancy from a custom library or anything like that.
It appears this first bit:
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(callback, state);
makes it fail. If I change it to:
int maxSize = 0x2000; // 8K
AsyncCallback callback = new AsyncCallback(AcceptCallback);
object? state = this.listenSocket;
_ = this.listenSocket.BeginAccept(maxSize, callback, state);
it succeeds, no exception anymore on EndAccept and I get the expected data in my ReceiveCallback (the next step in the asynchronous flow).
Because I was new to socket programming I figured it would be wise to start simple so I used the BeginAccept overload with the least parameters. I assumed it would use a default for maximum size. Well, whatever that "simple" overload does, it is not good.
So the type System.Threading.Tasks.TaskToApm.TaskAsyncResult for the result argument of AcceptCallback is perfectly fine, no problem there (I checked, it is still the same).
I can proceed now.

Caught OutOfMemoryException makes debugging difficult

When I debug my program, and try to do certain things in the immediate window, it sometimes shows an error message in the immediate window saying:
The function evaluation was disabled because of an out of memory
exception.
It also shows that when viewing the properties of object by hovering over them.
After trying to find the cause of the problem, I narrowed it down to this small code sample:
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
try
{
//outofmemoryexception can be thrown by Image.FromFile("path/that/does/not/exist.png")
//if the path points to a file that is not an image
throw new OutOfMemoryException();
}
catch (OutOfMemoryException ex)
{
//caught the exception
//so no problem, right?
}
//Random object to use in immediate window
Random rand = new Random();
//Also, try hovering over this regex and take a look at its properties.
var test = new Regex("");
//put a breakpoint here (at the next closing curly brace) and try calling rand.Next() in the immediate window
}
}
}
It seems that the debugger freaks out when an OutOfMemoryException occurs, even when it's caught...
I can imagine that no one ever thought it would be possible to debug a program that has had an OutOfMemoryException. But sadly enough Image.FromFile throws that error when the file is not an image...
Questions:
Does the above code sample give problems to anyone else?
Can someone clarify this a bit? Why does this happen exactly?
And lastly, how can I prevent this?
Yes, it is expected behavior.
You need to let debugger to run (step over or put breakpoint on next line and click F5) for it to recover from such state. Even that sometimes it does not help and running till you hit some other function higher on the stack usually makes debugger to cooperate again.
Note that OOM is not the only case - i.e. long running code in Immediate window will get debugger into the same state.
More information - MSDN Function evaluation is disabled..., SO - Function evaluation disabled because a previous function evaluation timed out

StreamReader ReadLine returns null when not EOF

Having a strange problem that I've never encountered nor heard of happening. It seems that occasionally, the ReadLine() function of the StreamReader class will return NULL, as if it's at the end of the file, BUT it's not.
My log file indicates that everything is happening just as if it had actually reached the end of the file, but yet it's only processing part of it. There doesn't appear to be any consistency, because if I restart the process from scratch, the whole file is processed without incident.
Clearly, there is nothing funky in the file itself, or it would do this on the same line each time, plus it has happened with a few different files, and each time they are re-run, it works fine.
Anyone run across anything similar, or have any suggestions on what might be causing such a thing?
Thanks,
Andrew
Sample:
line = _readerStream.ReadLine();
if (null != line)
{
eventRetVal = loadFileLineEvent(line);
}
else
{
// do some housecleaning and log file completed
}
_readerStream is the stream which has been opened elsewhere.
loadFileLineEvent is a delegate that gets passed in which processes the line. This has its own error handling (with logging), so there's no issue in there.
The routine above (not shown in its entirety) has error handling around it also (with logging), which is not being triggered either.
It's getting to the "else" and logging that it reached the end of the file, but it's obvious from the number of records I got that it didn't.
Have you tried a more traditional approach to reading the stream? This way your checking for the end of the stream before reading the next potentially empty/null line. Seems like your code should work, but with a possible null exception thrown for trying to read a line that doesn't exists(not sure if SR throws for that though).
using (StreamReader SR = new StreamReader(OFD.FileName))
{
while (!SR.EndOfStream)
{
string CurrentLine = SR.ReadLine();
var eventRetVal = loadFileLineEvent(CurrentLine);
}
}

Running Async Method in Loop without Stackoverflow Exception

This piece of code keeps throwing a stackoverflow exception and I have a feeling it's either because of the await keyword causing the stack to fill up, or a thread availability issue. However, I'm not sure what the best way of remedying this would be.
The results variable is just a collection of StorageFiles and if it's above 1020 or so, the exception is thrown; otherwise it's usually fine.
private async void GetMusicTest()
{
var sfolder = await StorageFolder.GetFolderFromPathAsync(dir);
var query = sfolder.CreateFileQueryWithOptions(queryOptions);
var results = await query.GetFilesAsync();
for (int i = 0; i < results.Count; i++)
{
MusicProperties mp = await results[i].Properties.GetMusicPropertiesAsync();
Debug.WriteLine(mp.Title);
}
}
This code works fine in a console application, but the error is thrown when used in a desktop WinForm app.
Interestingly, if result.Count() is used instead, then the error is thrown after three iterations, whereas results.Count throws it after iterating through at least half of the collection, if not all (it seems to vary). They both return the same values. What's the best way looping through without causing a stackoverflow exception or using up all available threads?
I think this is a bug that should be addressed.
If I'm right, you can work around it by occasionally doing an await Task.Yield() within your loop.

Memory exception while XDocument.Save()

I am trying to save an XDcoument to a thumb drive which doesnt have enough memory space available. (This is a special test condition for the app) Though the application is giving an exception like below, I cant get that in the try catch block around the XDocument.Save(filePath). Looks like it is a delayed throw. Is it a LINQ issue or am I doing something wrong?.
alt text http://img211.imageshack.us/img211/8324/exce.png
System.IO.IOException was unhandled
Message="There is not enough space on the disk.\r\n"
Source="mscorlib"
StackTrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.FileStream.FlushWrite(Boolean calledFromFinalizer)
at System.IO.FileStream.Dispose(Boolean disposing)
at System.IO.FileStream.Finalize()
You found a bug in the framework. XDocument.Save(string) uses the "using" statement to ensure the output stream gets disposed. It depends on the encoding you used in the processing instruction but the internal System.Xml.XmlUtf8RawTextReader would be a common one to implement the text writer.
The bug: the Microsoft programmer that wrote that class forgot to implement the Dispose() method. Only the Close() method is implemented.
It is rather strange that this bug wasn't yet reported at the connect.microsoft.com feedback site. It ought to cause trouble in general use because the file stays open until the finalizer thread runs. Although that normally doesn't take that long, a couple of seconds or so. Except in your case where you exit the program right after writing and have the unfortunate luck to run out of disk space at the exact moment the buffer gets flushed.
A workaround for this bug is to use the XDocument.Save(TextWriter) overload instead, passing a StreamWriter whose Encoding matches the encoding of the XML.
Look at the stack trace. This trace starts with a Finalize call, which does a Dispose, which does a FlushWrite, which calls WriteCore, which gets the error.
In other words, flush your data first.
Post the code you use to write and we can show you where to do the flush.
Peeking into reflector, the last few lines are
using (XmlWriter writer = XmlWriter.Create(fileName, xmlWriterSettings))
{
this.Save(writer);
}
It means, the exception is thrown when the writer is disposed.
I guess, it will be better to check for available disk space before calling Save.
EDIT: Have you Disposed any object that the instance of XDocument depended on before making a call to Save?
XDocument.Save(string) does not have a bug, it does implement the Dispose method. The using statement is:- (as also described above)
using (XmlWriter writer = XmlWriter.Create(fileName, xmlWriterSettings))
this.Save(writer);
And XmlWriter does have a Dispose(), it implement the IDisposable interface.

Categories

Resources