Global default uncaught exception handling
This commit is contained in:
parent
636f77409f
commit
e9cf8bb53f
2 changed files with 46 additions and 8 deletions
|
@ -73,6 +73,13 @@ public class FTLModManager {
|
||||||
log.debug( "OS: {} {}", System.getProperty( "os.name" ), System.getProperty( "os.version" ) );
|
log.debug( "OS: {} {}", System.getProperty( "os.name" ), System.getProperty( "os.version" ) );
|
||||||
log.debug( "VM: {}, {}, {}", System.getProperty( "java.vm.name" ), System.getProperty( "java.version" ), System.getProperty( "os.arch" ) );
|
log.debug( "VM: {}, {}, {}", System.getProperty( "java.vm.name" ), System.getProperty( "java.version" ), System.getProperty( "os.arch" ) );
|
||||||
|
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
|
@Override
|
||||||
|
public void uncaughtException( Thread t, Throwable e ) {
|
||||||
|
log.error( "Uncaught exception in thread: "+ t.toString(), e );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if ( args.length > 0 ) {
|
if ( args.length > 0 ) {
|
||||||
SlipstreamCLI.main( args );
|
SlipstreamCLI.main( args );
|
||||||
return;
|
return;
|
||||||
|
@ -348,14 +355,26 @@ public class FTLModManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the main window.
|
// Create the main window.
|
||||||
|
ManagerFrame frame = null;
|
||||||
try {
|
try {
|
||||||
ManagerFrame frame = new ManagerFrame( appConfig, APP_NAME, APP_VERSION, APP_URL, APP_AUTHOR );
|
frame = new ManagerFrame( appConfig, APP_NAME, APP_VERSION, APP_URL, APP_AUTHOR );
|
||||||
frame.init();
|
frame.init();
|
||||||
frame.setVisible( true );
|
frame.setVisible( true );
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
log.error( "Exception while creating ManagerFrame", e );
|
log.error( "Exception while creating ManagerFrame", e );
|
||||||
|
|
||||||
|
// If the frame is constructed, but an exception prevents it
|
||||||
|
// becoming visible, that *must* be caught. The frame registers
|
||||||
|
// itself as a global uncaught exception handler. It doesn't
|
||||||
|
// dispose() itself in the handler, so EDT will wait forever
|
||||||
|
// for an invisible window to close.
|
||||||
|
|
||||||
|
if ( frame != null && frame.isDisplayable() ) {
|
||||||
|
frame.setDisposeNormally( false );
|
||||||
|
frame.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
throw new ExitException();
|
throw new ExitException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,10 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
private File appUpdateFile = new File( backupDir, "auto_update.json" );
|
private File appUpdateFile = new File( backupDir, "auto_update.json" );
|
||||||
private File appUpdateETagFile = new File( backupDir, "auto_update_etag.txt" );
|
private File appUpdateETagFile = new File( backupDir, "auto_update_etag.txt" );
|
||||||
|
|
||||||
|
private boolean disposeNormally = true;
|
||||||
|
private boolean ranInit = false;
|
||||||
|
private Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler = null;
|
||||||
|
|
||||||
private final Lock managerLock = new ReentrantLock();
|
private final Lock managerLock = new ReentrantLock();
|
||||||
private final Condition scanEndedCond = managerLock.newCondition();
|
private final Condition scanEndedCond = managerLock.newCondition();
|
||||||
private boolean scanning = false;
|
private boolean scanning = false;
|
||||||
|
@ -113,8 +117,8 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
private String appURL;
|
private String appURL;
|
||||||
private String appAuthor;
|
private String appAuthor;
|
||||||
|
|
||||||
private HashMap<File,String> modFileHashes = new HashMap<File,String>();
|
private Map<File,String> modFileHashes = new HashMap<File,String>();
|
||||||
private HashMap<String,Date> modFileDates = new HashMap<String,Date>();
|
private Map<String,Date> modFileDates = new HashMap<String,Date>();
|
||||||
private ModDB catalogModDB = new ModDB();
|
private ModDB catalogModDB = new ModDB();
|
||||||
private ModDB localModDB = new ModDB();
|
private ModDB localModDB = new ModDB();
|
||||||
|
|
||||||
|
@ -261,6 +265,12 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
@Override
|
@Override
|
||||||
public void windowClosed( WindowEvent e ) {
|
public void windowClosed( WindowEvent e ) {
|
||||||
// dispose() was called.
|
// dispose() was called.
|
||||||
|
|
||||||
|
// Restore the previous exception handler.
|
||||||
|
if ( ranInit ) Thread.setDefaultUncaughtExceptionHandler( previousUncaughtExceptionHandler );
|
||||||
|
|
||||||
|
if ( !disposeNormally ) return; // Something bad happened. Exit quickly.
|
||||||
|
|
||||||
ListState<ModFileInfo> tableState = getCurrentModsTableState();
|
ListState<ModFileInfo> tableState = getCurrentModsTableState();
|
||||||
saveModsTableState( tableState );
|
saveModsTableState( tableState );
|
||||||
|
|
||||||
|
@ -404,9 +414,14 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extra initialization that must be called after the constructor.
|
* Extra one-time initialization that must be called after the constructor.
|
||||||
*/
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
|
if ( ranInit ) return;
|
||||||
|
ranInit = true;
|
||||||
|
|
||||||
|
previousUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler( this );
|
||||||
|
|
||||||
ManagerInitThread initThread = new ManagerInitThread(
|
ManagerInitThread initThread = new ManagerInitThread(
|
||||||
this,
|
this,
|
||||||
|
@ -421,7 +436,6 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
);
|
);
|
||||||
initThread.setDaemon( true );
|
initThread.setDaemon( true );
|
||||||
initThread.setPriority( Thread.MIN_PRIORITY );
|
initThread.setPriority( Thread.MIN_PRIORITY );
|
||||||
initThread.setDefaultUncaughtExceptionHandler( this );
|
|
||||||
initThread.start();
|
initThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +538,6 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
ModsScanThread scanThread = new ModsScanThread( modFiles, localModDB, this );
|
ModsScanThread scanThread = new ModsScanThread( modFiles, localModDB, this );
|
||||||
scanThread.setDaemon( true );
|
scanThread.setDaemon( true );
|
||||||
scanThread.setPriority( Thread.MIN_PRIORITY );
|
scanThread.setPriority( Thread.MIN_PRIORITY );
|
||||||
scanThread.setDefaultUncaughtExceptionHandler( this );
|
|
||||||
scanThread.start();
|
scanThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +739,6 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
log.info( "Patching..." );
|
log.info( "Patching..." );
|
||||||
log.info( "" );
|
log.info( "" );
|
||||||
ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, false, patchDlg );
|
ModPatchThread patchThread = new ModPatchThread( modFiles, datsDir, backupDir, false, patchDlg );
|
||||||
patchThread.setDefaultUncaughtExceptionHandler( this );
|
|
||||||
patchThread.start();
|
patchThread.start();
|
||||||
|
|
||||||
patchDlg.setVisible( true );
|
patchDlg.setVisible( true );
|
||||||
|
@ -801,7 +813,6 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
File datsDir = new File( appConfig.getProperty( SlipstreamConfig.FTL_DATS_PATH ) );
|
File datsDir = new File( appConfig.getProperty( SlipstreamConfig.FTL_DATS_PATH ) );
|
||||||
|
|
||||||
DatExtractDialog extractDlg = new DatExtractDialog( this, extractDir, datsDir );
|
DatExtractDialog extractDlg = new DatExtractDialog( this, extractDir, datsDir );
|
||||||
extractDlg.getWorkerThread().setDefaultUncaughtExceptionHandler( this );
|
|
||||||
extractDlg.extract();
|
extractDlg.extract();
|
||||||
extractDlg.setVisible( true );
|
extractDlg.setVisible( true );
|
||||||
}
|
}
|
||||||
|
@ -1048,6 +1059,14 @@ public class ManagerFrame extends JFrame implements ActionListener, ModsScanObse
|
||||||
updateBtn.setEnabled( isUpdateAvailable );
|
updateBtn.setEnabled( isUpdateAvailable );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles whether to perform the usual actions after disposal.
|
||||||
|
*
|
||||||
|
* Set this to false before an abnormal exit.
|
||||||
|
*/
|
||||||
|
public void setDisposeNormally( boolean b ) {
|
||||||
|
disposeNormally = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException( Thread t, Throwable e ) {
|
public void uncaughtException( Thread t, Throwable e ) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue