I've been searching, but not finding, so I thought I'd ask.
When using a log4net appender that buffers, do I need to call some kind of flush on application exit or does log4net take care of that itself?
You can check the source code at http://svn.apache.org/repos/asf/logging/log4net/trunk/src/log4net/Appender/
But basically, as I understand it, if your program closes down correctly, then the appenders should be flushed.
AdoNetAppender inherits from BufferingAppenderSkeleton which inherits from AppenderSkeleton and
so the finalizer on class AppenderSkeleton will call Close() on your AdoNetAppender which calls base.Close() and the base class is BufferingAppenderSkeleton and this methods calls Flush().
Of course, there are times when your finalizer does not run (See Are .net finalizers always executed?)
Related
The Log4net FAQ says that log4net is thread-safe:
Question: Is log4net thread-safe?
Answer: Yes, log4net is thread-safe.
However, the manual for the AdoNetAppender class says the following:
Instance members are not guaranteed to be thread-safe.
My guess is that log4net is not thread-safe. I'm using this class to log into a database, and manually flushing the appended data from time to time. I see that some records are duplicated.
Looking at the code, it appears to me that the base class BufferingAppenderSkeleton locks the object for the flush(), however the function SendFromBuffer() which is eventually called can be invoked from other places without lock (for instance Append()). Therefore, it appears that the class is not thread-safe.
So should I conclude that the class is not thread-safe, however the usage in log4net makes it so?
I am working with a COM interface that, according to ThreadingModel = "Free" in it's CLSID entry in the registry, supports multithreaded apartments. Multithreading seems to be implemented at a very basic level, however, very often method calls return a "Class is busy" status code.
Is there any risk of switching to STAs in CoInitializeEx and using interface marshaling to have the COM system serialize the requests and to avoid this behaviour (which I never experienced when only making calls from the main thread)?
Thanks!
Using an STA thread to host the COM object will not make any difference. COM pays attention to the ThreadingModel value in the registry. Since it is "Free", it will not see any need to marshal the interface pointer and will still makes the call from the worker thread.
You would have to monkey with the registry key and change it to "Both".
This is not a great solution, it will break at a drop of a hat. It is just far better to take care of this yourself. Use Control.Begin/Invoke() or Dispatcher.Begin/Invoke(), depending on which class library you use to implement the required message loop. Note that you now also have a choice, the COM marshaling is equivalent to Invoke() but you can (possibly) optimize by using BeginInvoke().
And last but not least, duplicating the locking that exists in the COM server that produces the "busy" error code is a possible solution. Non-zero odds that you'll solve this by acquiring your own lock before you make each call, thus serializing the calls yourself. Your worker thread will now block instead of having to deal with the error code. Contacting the author of the component would be wise, he can easily tell you which specific methods you should serialize.
I have a custom logging class for my Python script with a flush() method which print()s the contents of a list.
I would like to include flush() in the special __del__() method in case the program ends without the log being flushed. However a note in the documentation states:
[...] when del() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the del() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down).
Would anyone recommend a different way of doing this, and if so, why?
You might want to look into making this logger a context manager. That still will not flush in the case of abnormal termination, but few things will. But __del__ might not be called on objects even in normal termination.
Loggers might be one of the things that doesn't fit well when using the with statement, as they are quite global, so it's not sure context manager is a good fit.
A lot of Java ME tutorials use the startApp() method for creating and initializing objects and the constructor is left blank. However, the startApp() method is also invoked when the MIDlet resumes from a paused state. This causes all the objects to be re-initialized and any changes made are lost.
I have also noticed that the netbeans IDE, in its auto-generated code, uses many if(object==null) statements in startApp() to check if the object was created earlier.
Would it not make sense to simply do all the object creation and initialization in the constructor itself? Is there any reason for not doing this?
This is in part about understanding the MIDP threading model.
What thread the MIDlet constructor is called in depends on who developed the Java Virtual Machine on the phone.
Developers have a tendency to rely only on what the MIDP specification says in that area, which is how startApp, pauseApp and lcdui event handling should behave.
However there are only a few cases where this is important.
The second aspect to this issue is software developers trying to free as much resources (memory, file handles, sockets...) as possible when the MIDlet is paused.
Again, there are cases when MIDlets should hang on to some resources even when paused but you really need to think about what you're doing (and understand it better than casually) when coding that kind of behavior.
It is also worth remembering that some phones always keep the JVM process running. When they also have a JVM that doesn't support class unloading (as is usual in a J2ME world), this means that static variables can remain in memory even after the MIDlet has been completely destroyed.
Forget for a second the question of why on earth would you do such a thing - if, for whatever reason, two FileAppenders are configured with the same file - will this setup work?
Log4j's FileAppender does not allow for two JVM's writing to the same file. If you try, you'll get a corrupt log file. However, logback, log4j's successor, in prudent mode allows two appenders even in different JVMs to write to the same file.
It doesn't directly answer your question, but log4*net*'s FileAppender has a LockingModel attribute that you can set to only lock when the file is actually in use. So if you had two FileAppenders working in the same thread with MinimalLock set, it would probably work perfectly fine. On different threads, you might hit deadlock once in a while.
The FileAppender supports pluggable file locking models via the LockingModel property. The default behavior, implemented by FileAppender.ExclusiveLock is to obtain an exclusive write lock on the file until this appender is closed. The alternative model, FileAppender.MinimalLock, only holds a write lock while the appender is writing a logging event.
A cursory web search didn't turn up any useful results about implementing MinimalLock in log4j.
From Log4j FAQ a3.3
How do I get multiple process to log to the same file?
You may have each process log to a SocketAppender. The receiving SocketServer (or SimpleSocketServer) can receive all the events and send them to a single log file.
As to what that actually means I will be investigating myself.
I also found the following workaround on another SO question:
Code + Example