Affects Version/s: 2.0.8
Fix Version/s: None
Environment:Windows, MS SQL Server 2016
I recently noticed a strange issue with log4net and the AdoNetAppender and it would be nice if anyone could comment on this.
Its quite an Edge Case I know but the implication is that the Application will freeze and no Exception is thrown which is kind of scary.
I have made a small example C# project to illustrate the issue which I can provide, but first I want to explain the issue.
The scenario is like this:
- Visual Studio C# Console Application. Log4net (latest version) embedded as dll, MS SQL Server 2016 (but I guess this doesn't matter), .NET Framework > 4.5
- The Application starts and the Logger is initialized (containing a AdoNetAppender pointing to an existing Database on MS SQL Server - localhost)
- The code is something like this:
- After that happened, the Application is going to DROP the Database containing the Table that log4net will log to and recreates the database with all tables
- This happens because every time the console starts the Log-Database should be empty (I know there are other ways like truncate oder Drop Table but lets stay with me to understand the problem)
- So at this point the Database containing the Log Table has been recreated.
- Now the Application starts a number Threads (in my example 64, but I guess it works with less) and waits for them to finish
- In the Do() Method of the Thread, the thread simply tries to log an Error Message to the previously initialized logger
- The Result is that the Application freezes and will never return (0% CPU). Also no log messages arrive in the database.
- I am guessing there is some kind of deadlock situation inside log4net if multiple threads try to "initialize" the database connection to the recreated database again but in detail I have no idea what happens.
- No exception is thrown, the threads just never finish there Do() Method
So if I skip the part where I Recreate the database (with DROP und CREATE Database), then it works.
Also if put a log statement after the recreation of the database but BEFORE the multithreaded part starts, it also works.