Bug 51597 - JDBCAppender not closed due to SQL Exception while executing an SQL
JDBCAppender not closed due to SQL Exception while executing an SQL
Status: RESOLVED FIXED
Product: Log4j
Classification: Unclassified
Component: Appender
unspecified
PC All
: P2 critical
: ---
Assigned To: log4j-dev
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2011-08-01 18:02 UTC by Anurag Agarwal
Modified: 2012-01-13 23:17 UTC (History)
1 user (show)



Attachments
Log4j-JDBC-Appender-Issue.doc (95.50 KB, application/msword)
2011-08-01 18:02 UTC, Anurag Agarwal
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Anurag Agarwal 2011-08-01 18:02:19 UTC
Created attachment 27339 [details]
Log4j-JDBC-Appender-Issue.doc

In JDBCAppender.java there is method execute(String sql). This method is used to insert the SQL into DB, but in case if anything wrong happen while inserting, then it throws one SQLException and closing only SQL statement but connection is not closed, and so Appender thread is still alive.

Now as the execute method is called via flushBuffer() method, this method is calling execute and then event is added to removes list, but if execute method had thrown the SQLException then the event is not added to removes list and removes list is growing continuously. And that is in the buffer tile next call of System.gc(), so this will make the next threads to go into hung state.

Code Snippet having issue is attached.
A solution to this is to have following implementation:

protected void execute(String sql) throws SQLException {
Connection con = null;
Statement stmt = null;
try {
	con = getConnection();
          stmt = con.createStatement();
             stmt.executeUpdate(sql);
     } catch (SQLException e) {
		throw e; 
         
      }finally{
	try{
	if(null != stmt)  
		stmt.close();
         closeConnection(con);

	} catch (SQLException e){
	
     	}
		
     }
}

public void flushBuffer() {
//Do the actual logging
removes.ensureCapacity(buffer.size());
for (Iterator i = buffer.iterator(); i.hasNext();) {
try {
  LoggingEvent logEvent = (LoggingEvent)i.next();
  String sql = getLogStatement(logEvent);
  removes.add(logEvent);
  execute(sql);
  }catch (SQLException e) {
  	errorHandler.error("Failed to excute sql", e,
		ErrorCode.FLUSH_FAILURE);
  }
 }
// remove from the buffer any events that were reported
buffer.removeAll(removes);
// clear the buffer of reported events
removes.clear();
}
Comment 1 grobmeier 2012-01-13 23:17:15 UTC
fixed with rv1231387

Thanks for the report!