My local test server crashes as soon as I'm trying to write to a logfile. I'm using this for an ASP.NET-Page, codebehind is C#.
Structure:
/
Functions.cs
index.aspx
index.aspx.cs
I create an instance of Functions as my index.aspx loads. In Functions, I define a function for logging, which is called from index.aspx.cs and looks like this:
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
_Writer is defined globally for the Class and contains, as you see, a StreamWriter. The class itself has a destructor to close any connections to the files;
~Functions()
{
_Writer.Flush();
_Writer.Close();
_Writer.Dispose();
}
So, when I open up my page, the logs are written but then the server crashes. So I assume the problem is somewhere in the descructor, but I can't figure out why...
You don't need any destructor, StreamWriter already have it's own.
You should not access other objects from a destructor as it will be called by the Garbage collector, the other objects are in an undeterminable state. You don't know when it will be called and you don't know on which thread it will be called.
NEVER, NEVER, NEVER write a destructor, it's almost always a bad idea.
You may place your cleanup code in the Unload event, see ASP.NET Page Life Cycle.
I'd recommend the using statement which automatically invokes the dispose call. For your purposes the code would look something like:
StreamWriter _Writer;
using(_Writer)
{
if (_WriterOpen == false)
{
_Writer = new StreamWriter(_WorkingDir + _Logfile, true);
_WriterOpen = true;
_Writer.AutoFlush = true;
}
_Writer.WriteLine(DateTime.Now.ToString() + ": " + String.Format(Note, Args));
}
Note I haven't tested this out but it should work (or at least be close). I'll update if needed after checking it out
Also see the following two articles:
Article 1
Article 2
This sounds most likely to be a stack overflow error, caused by a recursive call.
Are you logging an error, that is causing an error, that is logging, causing...etc.
Can you run it in debug mode from Visual Studio?
First: you don't need to call both close and dispose.
See the link from MSDN:
link text
This implementation of Close calls the Dispose method passing a true value.
You must call Close to ensure that all
data is correctly written out to the
underlying stream. Following a call to
Close, any operations on the
StreamWriter might raise exceptions.
If there is insufficient space on the
disk, calling Close will raise an
exception.
If you cant run it through in the debugger, try commenting lines out of Functions until it stops falling over. This should give you a clue.
The garbage collector will call the destructor at some indeterminate time, so if you are getting a regular crash, its probably not the destructor.
I would prefer to make the class inherit from IDisposable and put the clean up code in there. Use the dispose pattern : here
Related
So I'm working with cmdlets in C# and using a base cmdlet which derives from PSCmdlet.
Like this: Child <- Parent <- PSCmdlet.
We login to a system using methods in the Parent cmdlet. But sometimes things don't always go right with exceptions, crashes and so on. So it doesn't really logout properly.
My question is as follows:
Is there a method existing that I can implement/override in the Parent cmdlet that will run no matter what happens so that we properly can logout? Kind of like try finally.
I have checked out EndProcessing() and StopProcessing() but they aren't really up to the task in unforeseen situations.
Edit: To clarify, there are multiple cmdlets and the situation is not just about login. There are multiple exceptions that can occur based on code and user-input.
The solution for my problem, as #PetSerAl suggested, was to implement IDisposable in the Parent class.
Using Dispose() I could then add whatever methods needed to finalize the cmdlet no matter what happens.
This sounds like a good case to use Try-catch:
try
{
UserLogin();
OtherMethod();
}
catch(UnauthorizedException au)
{
Console.WriteLine("Unauthorized user... shutting down");
//Closing Code...
Environment.Exit(0);
}
catch(OtherException oe)
{
//Closing Code...
Environment.Exit(0);
}
...
Where you would (if not already) throw the UnauthorizedException() exception within UserLogin() or which ever method you are using to test credentials.
This concept can also be applied to the other areas of code that you are expecting exceptions to be thrown. If the exceptions are because of code not working properly, Try-Catch should not be used to suppress that error as it should be corrected. Exceptions/errors based off of User-Input could be wrapped with Try-Catch.
We had a problem recently where one of the developers had changed a line of code from using HttpResponse.End to using HttpApplication.CompleteRequest when forcing a PDF to download in a similar fashion to the following:
https://stackoverflow.com/a/8590579/3856039
Doing so caused some PDF's to fail to download due to a non-breaking space issue so the code was changed back to using HttpResponse.End.
However, in helping my colleague I was carrying out some research and I came across the following question:
Is Response.End() considered harmful?
Which links to:
https://blogs.msdn.microsoft.com/aspnetue/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation/
Given what is documented in the MSDN blog post, it sounds like using HttpResponse.End is the wrong approach, so I was wondering if it is even needed or whether there is a better approach?
Here is the actual code from Response.End:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
HttpResponse.AbortCurrentThread();
return;
}
this._endRequiresObservation = true;
if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
The ThreadAbortException is used for control of flow-- basically allowing you to use Response.End in place of return. But if you've designed your handler well, you may not need it, e.g. if there is no code after Response.End(). It is generally better not to throw the exception if you can avoid it, since it (like all exceptions) will cause a stack unwind and some performance overhead.
Perhaps you can write your own version of Response.End and pick and choose which lines of code actually execute, e.g. maybe you want to flush the buffer and call CompleteRequest but you don't want to throw the exception.
Here is the approach I have used in the past
// Sends all currently buffered output
HttpContext.Current.Response.Flush(); to the client.
// Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.Response.SuppressContent = true;
/* Causes ASP.NET to bypass all events and filtering in the HTTP pipeline
chain of execution and directly execute the EndRequest event. */
HttpContext.Current.ApplicationInstance.CompleteRequest();
I'm write XML AJAX Service with OPC server. XML AJAX Service based on this example.
And I made my service with single attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
And next step I'm create class destructor:
~BoilerService()
{
try
{
ReadTimer.Dispose();
group.ReadCompleted -= new ReadCompleteEventHandler(group_ReadCompleted);
group.Remove(true);
server.Disconnect();
}
catch (Exception e)
{
System.IO.StreamWriter sw = new System.IO.StreamWriter("log.txt", true);
sw.WriteLine(DateTime.Now.ToString() +e.Message+ " "+ e.Source+" "+e.StackTrace + " destructor called.");
sw.Close();
sw.Dispose();
}
}
But when I rebuild my solution in VS (files replaced in app path) I get wp3.exe unhandled exception error window (Windows 7). And in Windows event log I see folowing text:
Exception: System.Runtime.InteropServices.InvalidComObjectException
Message: COM object that has been separated from its underlying RCW cannot be used.
StackTrace: at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, Boolean& pfNeedsRelease)
at OPC.Data.Interface.IOPCServer.RemoveGroup(Int32 hServerGroup, Boolean bForce)
at OPC.Data.OpcGroup.Remove(Boolean bForce)
at OPC.Data.OpcGroup.Finalize()
What did I do wrong?
And VS 2010 give warnings:
1. 'System.Runtime.InteropServices.UCOMIEnumString' is obsolete: 'Use System.Runtime.InteropServices.ComTypes.IEnumString instead. http://go.microsoft.com/fwlink/?linkid=14202'.
2. 'System.Runtime.InteropServices.UCOMIConnectionPointContainer' is obsolete: 'Use System.Runtime.InteropServices.ComTypes.IConnectionPointContainer instead. http://go.microsoft.com/fwlink/?linkid=14202'
May be this error appear because of for this warnings?
According to the MSDN documentation
The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already finalized when the finalizer of Object A starts.
What this means is that if group is elegible for collection at the same time as your OpcGroup instance (which seems very likely) it may well be that group has already been finalised which could easily be the cause of your failure.
It looks like you are coming from a C++ background, in which case you should be aware that finalisers work differently in C# - its very rare that you ever need to implement a finaliser. I would recommend that instead of doing this clean up in your finaliser you instead implement IDisposable and do this work when the object is disposed.
Also you don't normally need to un-hook event handlers (unless the event may still be fired and could cause an exception after an object has ben disposed). This sort of clean up is handled for you.
First of all I am stumped. I have a search-module for a CMS that runs fine on one site, but it won't run as it's supposed to on another site.
I have this code I call both with an Ajax call and simply when loading the search site:
private string GetSearchContent()
{
Query q = GetQuery();
//for each area, set it up, perform search and render result
IArea products = new ProductArea(GetEcomExcludedGroupIDs(), GetEcomLanguage()).Search(q);
IArea pages = new PageArea(GetAreaId())
.Search(q);
IArea news = new NewsArea(GetIncludedNewsCategoryIDs())
.Search(q);
....
}
The important part here is the Search function. This is implemented in the classes, but for some reason the code won't be executed.
I have tried splitting the code up so I am sure that is where the error lies. The freaky part is that it does not throw any exceptions, but it just stops executing whenever I try to call the Search function. It doesn't even enter the function.
The Search function looks like this:
public override IArea Search(Query q)
{
log.Debug("Product search");
....
}
The function it overrides is simply an abstract function on an interface that declares the function.
I have tried copying the function to the same class that are executing it with no luck, and I have tried accessing other functions on the classes, and that worked fine.
My question is then. What could cause this behavior? I have tried looking around but couldn't really find any others with the same problem. And as mentioned before, the exact same code is running smoothly on another site.
I really hope someone can help me get closer to a fix, or at least to understand the problem.
The question is unanswerable as written. You assert that the Search method never runs, and that the faulty line is this one:
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
There are a few different things that could be wrong outside of the Search method:
The NewsArea constructor throws an exception
The GetIncludedNewsCategoryIDs method throws an exception
Either of the above could call into unmanaged code and generate a native Win32 exception, which under some circumstances will simple cause the process to terminate rather than ever returning to managed code.
You state that "there is no try-catch" -- all the more reason to disbelieve your assertion that the method just stops without throwing an exception. Try the following for diagnostic purposes:
try
{
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
}
catch (Exception e)
{
Logger.Log("Caught in the act: " + e.ToString());
throw;
}
If you've run this and still see that the execution stops without logging any exception, then we'll look at other possibilities.
i am having a problem with a ActiveX i am using via COM-Interop. it`s throwing an exception after i exit my Application and i am not sure if this is my fault or the fault of the ActiveX.
is the the correct way to initilize and release an ActiveX via COM-Interop?
Error Message
Sample Code which triggers the Exception
public void CreateInvoice()
{
String path = #"";
FaktNT.OLESrvClass OLESrv = null;
try
{
OLESrv = new FaktNT.OLESrvClass();
if (OLESrv.MandantLogin2() == 0)
{
try
{
//Do Stuff
}
catch (System.Exception ex)
{
//Log Error
throw;
}
finally
{
OLESrv.MandantLogout();
}
}
else
{
//Do Stuff
};
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(OLESrv);
OLESrv = null;
GC.Collect();
}
}
You should not need to release the COM object manually using Marshal.ReleaseComObject(). This is done by .net automatically (depending on what you are doing to the reference counting in the native COM code of course).
I would also try to check if the problem originates on the native side (for example in a destructor, which is called when the object is garbage collected).
Is the COM dll generating any native threads, which may be running after the object was garbage collected?
This is not a .NET message, the component itself is trapping the access violation exception. Looks like it was written in Delphi, judging from the exception name. Making native code bomb on an AV doesn't usually require a lot of help. But sure, you may be using the component 'incorrectly'. You stubbed out too much code to really make an informed guess. Other than that making calls on it in a finally block after you caught all exceptions that it might raise is a Bad Idea.
Getting it to bomb on program exit instead of after the GC.Collect() call is not healthy either. Sure sign that you haven't managed to call ReleaseComObject and null all the interface references. That's common, better to leave it up to the garbage collector to do it right. Albeit that this message box is going to bomb the finalizer thread. Yes, you probably need the vendor's help if a thorough code review doesn't help.
i solved the problem now. it was in fact me misusing the COM-Object, i missed to call OLESrv.EngineClose() which closes the COM-Object cleanly.
somehow this little piece of important informationen didn`t make it into the vendors documentation ...