diff --git a/Duplicati/GUI/MainForm.cs b/Duplicati/GUI/MainForm.cs index 227cbbfbc..b4af92564 100644 --- a/Duplicati/GUI/MainForm.cs +++ b/Duplicati/GUI/MainForm.cs @@ -319,6 +319,16 @@ namespace Duplicati.GUI { TrayIcon_MouseClick(sender, e); } + + private static void AbortOwnThread(object thread) + { + System.Threading.Thread.Sleep(5000); + if (Program.IsRunningMainLoop) + { + Program.IsRunningMainLoop = false; + ((System.Threading.Thread)thread).Abort(); + } + } private void TrayIcon_MouseClick(object sender, MouseEventArgs e) { @@ -521,7 +531,11 @@ namespace Duplicati.GUI Program.SingleInstance.SecondInstanceDetected -= new SingleInstance.SecondInstanceDelegate(SingleInstance_SecondInstanceDetected); EnsureBackupIsTerminated(e.CloseReason == CloseReason.UserClosing ? CloseReason.ApplicationExitCall : e.CloseReason); - } + + //The form occasionally hangs on Mono, so we force kill it after 5 secs if it did not quit itself + if (Library.Utility.Utility.IsMono) + new System.Threading.Thread(AbortOwnThread).Start (System.Threading.Thread.CurrentThread); + } private void SingleInstance_SecondInstanceDetected(string[] commandlineargs) { diff --git a/Duplicati/GUI/Program.cs b/Duplicati/GUI/Program.cs index 627ad53f7..b0886adeb 100644 --- a/Duplicati/GUI/Program.cs +++ b/Duplicati/GUI/Program.cs @@ -97,8 +97,14 @@ namespace Duplicati.GUI /// A value describing if Duplicati is running without a tray /// public static bool TraylessMode = Library.Utility.Utility.IsClientLinux ? true : false; - - /// + + /// + /// A flag indicating if the main message loop is still running, + /// used to force exit when running on OSX + /// + public static bool IsRunningMainLoop; + + /// /// The main entry point for the application. /// [STAThread] @@ -321,13 +327,20 @@ namespace Duplicati.GUI DisplayHelper = new MainForm(); DisplayHelper.InitialArguments = args; - + + Program.IsRunningMainLoop = true; Application.Run(DisplayHelper); + Program.IsRunningMainLoop = false; } catch (Exception ex) { - MessageBox.Show(string.Format(Strings.Program.SeriousError, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } + //If the helper thread aborts the main thread, it also sets IsRunningMainLoop to false + // and in that case we accept the abort call + if (ex is System.Threading.ThreadAbortException && !Program.IsRunningMainLoop) + System.Threading.Thread.ResetAbort(); + else + MessageBox.Show(string.Format(Strings.Program.SeriousError, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } try {