Browse Source

Fix resource (handle) leak when connection or database selection fails using MySQL connection

Hunter200165 3 months ago
parent
commit
f2e4227fc2
1 changed files with 29 additions and 13 deletions
  1. 29 13
      packages/fcl-db/src/sqldb/mysql/mysqlconn.inc

+ 29 - 13
packages/fcl-db/src/sqldb/mysql/mysqlconn.inc

@@ -658,19 +658,35 @@ var
   FullVersion: string;
 begin
   InitialiseMysql;
-  if not SkipLibraryVersionCheck then
-    begin
-    FullVersion:=strpas(mysql_get_client_info());
-    // Version string should start with version number:
-    // Note: in case of MariaDB version mismatch: tough luck, we report MySQL
-    // version only.
-    if (pos(MySQLVersion, FullVersion) <> 1) and
-       (pos(MariaDBVersion, FullVersion) <> 1) then
-      Raise EInOutError.CreateFmt(SErrVersionMisMatch,[ClassName,MySQLVersion,FullVersion]);
-    end;  
-  inherited DoInternalConnect;
-  ConnectToServer;
-  SelectDatabase;
+  try
+    if not SkipLibraryVersionCheck then
+      begin
+      FullVersion:=strpas(mysql_get_client_info());
+      // Version string should start with version number:
+      // Note: in case of MariaDB version mismatch: tough luck, we report MySQL
+      // version only.
+      if (pos(MySQLVersion, FullVersion) <> 1) and
+        (pos(MariaDBVersion, FullVersion) <> 1) then
+        Raise EInOutError.CreateFmt(SErrVersionMisMatch,[ClassName,MySQLVersion,FullVersion]);
+      end;  
+    inherited DoInternalConnect;
+    ConnectToServer;
+    SelectDatabase;
+  except
+    // If exception occurs when making connection to MySQL/MariaDB server or selecting db, the MySQL instance may already be allocated
+    // As exception is thrown, Connected will not be set to True, preventing DoInternalDisconnect to be called
+    // This leads to handle/resource leak (as DoInternalDisconnect is not called and does not release resources allocated by mysql_init)
+    // Therefore close the connection explicitely in case of exception
+    if Assigned(FMySQL) then begin 
+      mysql_close(FMySQL);
+      FMySQL := nil;
+    end;
+
+    ReleaseMySQL;
+
+    // And reraise the exception afterwards
+    raise;
+  end;
 end;
 
 procedure TConnectionName.DoInternalDisconnect;