1

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:

  • When I start App and close it by pressing [X] then all lock files from "C:\ProgramData\firebird" are removed, but when App starts Updater and closes itself then the lock files stay untouched. I think that's why Hibernate cannot begin transaction.
  • Updater's process is not subprocess of App (I checked this using process monitor)
  • When I directly start Updater it works like a charm - so the problem shows up only when App starts Updater.

Things I can't do:

  • switch database to anything else - it has to be firebird embedded
  • move export function to Updater

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();
}
straw
  • 33
  • 6
  • Please show the minimum code necessary to reproduce this. Also include the Firebird embedded version, and the Jaybird version you are using. – Mark Rotteveel Nov 23 '16 at 18:05
  • 2
    Without seeing any code, I guess you should do a graceful shutdown of your app instead of just calling exit(). – Henry Nov 23 '16 at 18:19
  • I cannot post source code because it doesn't belong to me, but I'll try to provide some sinippets. I'll also provide more info about firebird. – straw Nov 23 '16 at 18:37
  • Calling `Platform.exit()` likely terminates the application, and - iirc - child applications. This probably means that Firebird embedded does not shutdown cleanly, and might also mean that the process started using `ProcessBuilder` also gets killed. – Mark Rotteveel Nov 24 '16 at 11:56

1 Answers1

1

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;
    }

}
straw
  • 33
  • 6