javawindowsjavafxfirebirdfirebird-embedded

Java doesn't release all resources on app close


I have two javafx apps an App and Updater. App uses Firebird database to store some fragile user data. Database runs in embedded mode (I think it's relevant), so that means that there can be only one connection to the database at the same time (database creates a lock file). Updater updates App.

The whole schema looks like this:

  1. User runs App-> App is checking if an update is required if it is then it starts Updater (Using java ProcessBuilder) and closes itself (Platform.exit()).
  2. Updater checks if App has been terminated properly.
  3. Updater runs command "App --export-user-data" (also using ProcessBuilder) to export the most important things before starting an update (has to be done this way - I cannot move this function to Updater).
  4. App freezes on first session.beginTransaction() - there is no single error or exception

What I have observed till now:

Things I can't do:

I would be greatful for even weirdest ideas because I spent four days trying to solve this problem.

edit: Firebird version: 2.1 Jaybird version: 2.1.6

The way Updater is started (only necessary things)

public void startUpdater(){
    ProcessBuilder pb = new ProcessBuilder(updaterPath, argument)
    pb.start();
    Platform.exit();
}

Solution

  • After long battle I finaly have a solution. When java creates a new process the child-process inherits all handles from it's parent. And that is why firebird lock files haven't been removed. I solved this by creating small app in cpp and using it as a proxy when running updater.

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    int _tmain( int argc, TCHAR *argv[] )
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
    
        if( argc != 2 )
        {
            printf("Usage: %s [cmdline]\n", argv[0]);
            return 0;
        }
    
        // Start the child process. 
        if( !CreateProcess( NULL,   // No module name (use command line)
            argv[1],        // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi )           // Pointer to PROCESS_INFORMATION structure
        ) 
        {
            printf( "CreateProcess failed (%d).\n", GetLastError() );
            return 0;
        }
    
    }