Update issue #185
Status: Fixed The code to support this was already in place, but did not work because Application.Exit() had been invoked, making all messageboxes return Cancel without showing. I also improved the logic a bit so a cancel does not invoke the cleanup afterwards, making the exit procedure faster. I also added checks for the stop command to the code that fetches the signature files, to make the application respond faster to the stop command. git-svn-id: https://duplicati.googlecode.com/svn/trunk@490 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
@@ -59,6 +59,7 @@ namespace Duplicati.GUI
|
||||
string destination = task.GetConfiguration(options);
|
||||
|
||||
string results = "";
|
||||
bool isAbortException = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -224,7 +225,12 @@ namespace Duplicati.GUI
|
||||
{
|
||||
//TODO: Extract ex.Message and save it in seperate field in the database
|
||||
if (ex is System.Threading.ThreadAbortException)
|
||||
{
|
||||
isAbortException = true;
|
||||
System.Threading.Thread.ResetAbort();
|
||||
}
|
||||
else if (ex is Library.Main.LiveControl.ExecutionStoppedException)
|
||||
isAbortException = true;
|
||||
|
||||
while (ex is System.Reflection.TargetInvocationException && ex.InnerException != null)
|
||||
ex = ex.InnerException;
|
||||
@@ -240,7 +246,7 @@ namespace Duplicati.GUI
|
||||
|
||||
try
|
||||
{
|
||||
if (task.TaskType == DuplicityTaskType.FullBackup || task.TaskType == DuplicityTaskType.IncrementalBackup)
|
||||
if (!isAbortException && (task.TaskType == DuplicityTaskType.FullBackup || task.TaskType == DuplicityTaskType.IncrementalBackup))
|
||||
{
|
||||
if (task.Schedule.Task.KeepFull > 0)
|
||||
{
|
||||
|
||||
@@ -179,6 +179,15 @@ namespace Duplicati.GUI
|
||||
|
||||
Program.LiveControl.Pause();
|
||||
Program.Runner.Stop();
|
||||
|
||||
TrayIcon.Visible = false;
|
||||
if (StatusDialog != null && StatusDialog.Visible)
|
||||
StatusDialog.Close();
|
||||
if (WizardDialog != null && WizardDialog.Visible)
|
||||
WizardDialog.Close();
|
||||
|
||||
EnsureBackupIsTerminated();
|
||||
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
@@ -305,5 +314,61 @@ namespace Duplicati.GUI
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void EnsureBackupIsTerminated()
|
||||
{
|
||||
if (Program.Runner != null && Program.WorkThread != null && Program.WorkThread.Active)
|
||||
{
|
||||
//Make sure no new items can enter the queue
|
||||
if (Program.Scheduler != null)
|
||||
Program.Scheduler.Terminate(true);
|
||||
|
||||
//We want no new items to enter the queue
|
||||
Program.WorkThread.Terminate(false);
|
||||
|
||||
Program.Runner.Pause();
|
||||
if (!Program.Runner.IsStopRequested)
|
||||
Program.Runner.Stop();
|
||||
|
||||
//Wait 15 seconds to see if the stop works
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
Program.WorkThread.Join(1000);
|
||||
Application.DoEvents();
|
||||
if (!Program.WorkThread.Active)
|
||||
break;
|
||||
}
|
||||
|
||||
while (Program.WorkThread.Active)
|
||||
{
|
||||
//Ask the user if we should abort
|
||||
if (MessageBox.Show(Strings.Program.TerminateForExitQuestion, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
|
||||
{
|
||||
//Abort the thread
|
||||
Program.Runner.Terminate();
|
||||
|
||||
//Give last 5 second chance to write the remaining data
|
||||
int i = 5;
|
||||
while (i > 0 && !Program.WorkThread.Join(1000))
|
||||
{
|
||||
//The Join call blocks the main thread, so let pending events through
|
||||
Application.DoEvents();
|
||||
i--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//Wait 18 * 10 seconds = 3 minutes before asking again
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
Program.WorkThread.Join(1000 * 10);
|
||||
Application.DoEvents();
|
||||
|
||||
if (!Program.WorkThread.Active)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,38 +207,6 @@ namespace Duplicati.GUI
|
||||
MessageBox.Show(string.Format(Strings.Program.SeriousError, ex.ToString()), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
if (Runner != null && WorkThread != null && WorkThread.Active)
|
||||
{
|
||||
Runner.Pause();
|
||||
if (!Runner.IsStopRequested)
|
||||
Runner.Stop();
|
||||
|
||||
//Wait 10 seconds to see if the stop works
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
if (!WorkThread.Active)
|
||||
break;
|
||||
}
|
||||
|
||||
while (WorkThread.Active)
|
||||
{
|
||||
if (MessageBox.Show(Strings.Program.TerminateForExitQuestion, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
|
||||
{
|
||||
Runner.Terminate();
|
||||
System.Threading.Thread.Sleep(500);
|
||||
break;
|
||||
}
|
||||
|
||||
//Wait 18 * 10 seconds = 3 minutes before asking again
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
System.Threading.Thread.Sleep(1000 * 10);
|
||||
if (!WorkThread.Active)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Scheduler != null)
|
||||
Scheduler.Terminate(true);
|
||||
|
||||
@@ -273,6 +273,11 @@ namespace Duplicati.GUI
|
||||
(m_form as Form).ShowDialog();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if ((m_form as Form).Visible)
|
||||
(m_form as Form).Close();
|
||||
}
|
||||
|
||||
private bool AskToResumeIfPaused()
|
||||
{
|
||||
|
||||
@@ -295,5 +295,17 @@ namespace Duplicati.GUI
|
||||
m_state = RunState.Paused;
|
||||
m_event.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits the specified number of milliseconds for the thread to terminate
|
||||
/// </summary>
|
||||
/// <param name="millisecondTimeout">The number of milliseconds to wait</param>
|
||||
/// <returns>True if the thread is terminated, false if a timeout occured</returns>
|
||||
public bool Join(int millisecondTimeout)
|
||||
{
|
||||
if (m_thread != null)
|
||||
return m_thread.Join(millisecondTimeout);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,6 +574,11 @@ namespace Duplicati.Library.Main
|
||||
m_statistics.NumberOfRemoteCalls++;
|
||||
return m_backend.List();
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException tex)
|
||||
{
|
||||
lastEx = tex;
|
||||
retries = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lastEx = ex;
|
||||
@@ -601,6 +606,11 @@ namespace Duplicati.Library.Main
|
||||
m_backend.Delete(remote.Filename);
|
||||
lastEx = null;
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException tex)
|
||||
{
|
||||
lastEx = tex;
|
||||
retries = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lastEx = ex;
|
||||
@@ -682,7 +692,7 @@ namespace Duplicati.Library.Main
|
||||
{
|
||||
try
|
||||
{
|
||||
using(Library.Interface.IEncryption enc = DynamicLoader.EncryptionLoader.GetModule(remote.EncryptionMode, m_options.Passphrase, m_options.RawOptions))
|
||||
using (Library.Interface.IEncryption enc = DynamicLoader.EncryptionLoader.GetModule(remote.EncryptionMode, m_options.Passphrase, m_options.RawOptions))
|
||||
enc.Decrypt(tempfile, filename);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -724,6 +734,11 @@ namespace Duplicati.Library.Main
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException tex)
|
||||
{
|
||||
lastEx = tex;
|
||||
retries = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lastEx = ex;
|
||||
@@ -821,9 +836,8 @@ namespace Duplicati.Library.Main
|
||||
}
|
||||
catch (System.Threading.ThreadAbortException tex)
|
||||
{
|
||||
//Do not retry after we are aborted
|
||||
lastEx = tex;
|
||||
break;
|
||||
retries = 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -197,8 +197,12 @@ namespace Duplicati.Library.Main
|
||||
entries.Add(backupsets[backupsets.Count - 1]);
|
||||
entries.AddRange(backupsets[backupsets.Count - 1].Incrementals);
|
||||
|
||||
//Check before we start the download
|
||||
CheckLiveControl();
|
||||
patches = FindPatches(backend, entries, tempfolder);
|
||||
|
||||
//Check before we start the download
|
||||
CheckLiveControl();
|
||||
Manifestfile latest = GetManifest(backend, backupsets[0]);
|
||||
|
||||
//Manifest version 1 does not support multiple folders
|
||||
@@ -1136,7 +1140,6 @@ namespace Duplicati.Library.Main
|
||||
{
|
||||
m_progress += unitCost;
|
||||
|
||||
|
||||
OperationProgress(this, DuplicatiOperation.Backup, (int)(m_progress * 100), -1, string.Format(Strings.Interface.StatusReadingManifest, be.Time.ToShortDateString() + " " + be.Time.ToShortTimeString()), "");
|
||||
|
||||
Manifestfile manifest = GetManifest(backend, be);
|
||||
@@ -1157,6 +1160,9 @@ namespace Duplicati.Library.Main
|
||||
|
||||
string filename = System.IO.Path.Combine(tempfolder, "patch-" + patches.Count.ToString() + ".zip");
|
||||
|
||||
//Check just before we download stuff
|
||||
CheckLiveControl();
|
||||
|
||||
using (new Logging.Timer("Get " + bes.Key.Filename))
|
||||
backend.Get(bes.Key, filename, manifest.SignatureHashes == null ? null : manifest.SignatureHashes[bes.Key.Volumenumber - 1]);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ using System.Text;
|
||||
|
||||
namespace Duplicati.Library.Main.LiveControl
|
||||
{
|
||||
class ExecutionStoppedException : Exception
|
||||
public class ExecutionStoppedException : Exception
|
||||
{
|
||||
public ExecutionStoppedException()
|
||||
: base(Strings.ExecutionStoppedException.DefaultMessage)
|
||||
|
||||
@@ -1558,17 +1558,26 @@ namespace Duplicati.Library.Main.RSync
|
||||
{
|
||||
BackupStatistics bs = m_stat as BackupStatistics;
|
||||
|
||||
bs.DeletedFiles = m_deletedfiles.Count;
|
||||
bs.DeletedFolders = m_deletedfolders.Count;
|
||||
bs.ModifiedFiles = m_diffedfiles;
|
||||
bs.AddedFiles = m_addedfiles;
|
||||
bs.ExaminedFiles = m_examinedfiles;
|
||||
bs.SizeOfModifiedFiles = m_diffedfilessize;
|
||||
bs.SizeOfAddedFiles = m_addedfilessize;
|
||||
bs.SizeOfExaminedFiles = m_examinedfilesize;
|
||||
if (m_deletedfiles != null)
|
||||
bs.DeletedFiles = m_deletedfiles.Count;
|
||||
if (m_deletedfolders != null)
|
||||
bs.DeletedFolders = m_deletedfolders.Count;
|
||||
if (m_diffedfiles != null)
|
||||
bs.ModifiedFiles = m_diffedfiles;
|
||||
if (m_addedfiles != null)
|
||||
bs.AddedFiles = m_addedfiles;
|
||||
if (m_examinedfiles != null)
|
||||
bs.ExaminedFiles = m_examinedfiles;
|
||||
if (m_diffedfilessize != null)
|
||||
bs.SizeOfModifiedFiles = m_diffedfilessize;
|
||||
if (m_addedfilessize != null)
|
||||
bs.SizeOfAddedFiles = m_addedfilessize;
|
||||
if (m_examinedfilesize != null)
|
||||
bs.SizeOfExaminedFiles = m_examinedfilesize;
|
||||
if (m_unproccesed != null && m_unproccesed.Files != null)
|
||||
bs.UnprocessedFiles = m_unproccesed.Files.Count;
|
||||
bs.AddedFolders = m_newfolders.Count;
|
||||
if (m_newfolders != null)
|
||||
bs.AddedFolders = m_newfolders.Count;
|
||||
}
|
||||
|
||||
if (m_snapshot != null)
|
||||
|
||||
Reference in New Issue
Block a user