Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Skovhede <kenneth@hexad.dk>2016-04-13 12:44:21 +0300
committerKenneth Skovhede <kenneth@hexad.dk>2016-04-13 12:44:21 +0300
commit020471bb2a7cbc1021b9d280c8e575f4a3a1673e (patch)
tree077584df1edf508fcea05003f909546b87cc886f /Duplicati/Service
parentc71fb7c7b72de5151fcf4420a41cac21a7797e24 (diff)
Added a windows service
Diffstat (limited to 'Duplicati/Service')
-rw-r--r--Duplicati/Service/Program.cs2
-rw-r--r--Duplicati/Service/Runner.cs163
2 files changed, 113 insertions, 52 deletions
diff --git a/Duplicati/Service/Program.cs b/Duplicati/Service/Program.cs
index bf919e4c1..a7fdc7ca6 100644
--- a/Duplicati/Service/Program.cs
+++ b/Duplicati/Service/Program.cs
@@ -23,7 +23,7 @@ namespace Duplicati.Service
{
public static void Main(string[] args)
{
- using(var runner = new Runner())
+ using(var runner = new Runner(args))
runner.Wait();
}
diff --git a/Duplicati/Service/Runner.cs b/Duplicati/Service/Runner.cs
index 9aeb659c0..49a33a5ba 100644
--- a/Duplicati/Service/Runner.cs
+++ b/Duplicati/Service/Runner.cs
@@ -23,12 +23,27 @@ namespace Duplicati.Service
{
private System.Threading.Thread m_thread;
private volatile bool m_terminate = false;
+ private volatile bool m_softstop = false;
private System.Diagnostics.Process m_process;
+ private Action m_onStartedAction;
+ private Action m_onStoppedAction;
+ private Action<string, bool> m_reportMessage;
+
+ private object m_writelock = new object();
+ private readonly string[] m_cmdargs;
+
private readonly int WAIT_POLL_TIME = (int)TimeSpan.FromMinutes(15).TotalMilliseconds;
- public Runner()
+ public Runner(string[] cmdargs, Action onStartedAction = null, Action onStoppedAction = null, Action<string, bool> logMessage = null)
{
+ m_onStartedAction = onStartedAction;
+ m_onStoppedAction = onStoppedAction;
+ m_reportMessage = logMessage;
+ if (m_reportMessage == null)
+ m_reportMessage = (x,y) => Console.WriteLine(x);
+
+ m_cmdargs = cmdargs;
m_thread = new System.Threading.Thread(Run);
m_thread.IsBackground = true;
m_thread.Name = "Server Runner";
@@ -41,76 +56,108 @@ namespace Duplicati.Service
var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
var exec = System.IO.Path.Combine(path, "Duplicati.Server.exe");
var cmdargs = Environment.CommandLine + " --ping-pong-keepalive=true";
+ if (m_cmdargs != null && m_cmdargs.Length > 0)
+ cmdargs = cmdargs + string.Join(" ", m_cmdargs);
if (cmdargs.StartsWith(self_exec))
cmdargs = cmdargs.Substring(self_exec.Length);
- if (!System.IO.File.Exists(exec))
- {
- Console.WriteLine("File not found {0}", exec);
- return;
- }
+ var firstRun = true;
+ var startAttempts = 0;
- while (!m_terminate)
+ try
{
- try
+ while (!m_terminate && !m_softstop)
{
- var pr = new System.Diagnostics.ProcessStartInfo(exec, cmdargs);
- pr.UseShellExecute = false;
- pr.RedirectStandardInput = true;
- pr.RedirectStandardOutput = true;
-
- if (!m_terminate)
- m_process = System.Diagnostics.Process.Start(pr);
+ if (!System.IO.File.Exists(exec))
+ {
+ m_reportMessage(string.Format("File not found {0}", exec), true);
+ return;
+ }
- while(!m_process.HasExited)
+ try
{
- m_process.WaitForExit(WAIT_POLL_TIME);
- if (!m_process.HasExited)
+ if (!firstRun)
+ m_reportMessage(string.Format("Attempting to restart server process: {0}", exec), true);
+
+ m_reportMessage(string.Format("Starting process {0} with cmd args {1}", exec, cmdargs), false);
+
+ var pr = new System.Diagnostics.ProcessStartInfo(exec, cmdargs);
+ pr.UseShellExecute = false;
+ pr.RedirectStandardInput = true;
+ pr.RedirectStandardOutput = true;
+
+ if (!m_terminate)
+ m_process = System.Diagnostics.Process.Start(pr);
+
+ if (firstRun && m_onStartedAction != null)
{
- if (m_terminate)
- m_process.Kill();
- else
- PingProcess();
+ PingProcess();
+ m_onStartedAction();
+ firstRun = false;
+ }
+
+ while (!m_process.HasExited)
+ {
+ m_process.WaitForExit(WAIT_POLL_TIME);
+ if (!m_process.HasExited)
+ {
+ if (m_terminate)
+ m_process.Kill();
+ else
+ PingProcess();
+ }
}
}
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
+ catch (Exception ex)
+ {
+ m_reportMessage(string.Format("Process has failed with error message: {0}", ex), true);
- // Throttle restarts
- if (!m_terminate)
- System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
+ if (firstRun)
+ {
+ startAttempts++;
+ if (startAttempts > 5)
+ {
+ m_reportMessage("Too many startup attempts, giving up", true);
+ m_terminate = true;
+ }
+ }
+
+ // Throttle restarts
+ if (!m_terminate)
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
+ }
}
}
+ finally
+ {
+ if (m_onStoppedAction != null)
+ m_onStoppedAction();
+ }
}
private void PingProcess()
{
for(var n = 0; n < 5; n++)
{
- m_process.StandardInput.WriteLine("ping");
- m_process.StandardInput.Flush();
+ lock(m_writelock)
+ {
+ m_process.StandardInput.WriteLine("ping");
+ m_process.StandardInput.Flush();
+ }
- string msg = null;
- System.Threading.ThreadPool.QueueUserWorkItem((x) =>
+ using (var t = m_process.StandardOutput.ReadLineAsync())
{
- Console.WriteLine("Reading...");
- msg = m_process.StandardOutput.ReadLine();
- Console.WriteLine("Read: {0}", msg);
- });
-
- var i = 10;
-
- while (string.IsNullOrWhiteSpace(msg) && i-- > 0)
- System.Threading.Thread.Sleep(TimeSpan.FromSeconds(6));
-
- if (!string.IsNullOrWhiteSpace(msg))
- return;
+ t.Wait(TimeSpan.FromMinutes(1));
+
+ if (t.IsCompleted && !t.IsFaulted && !t.IsCanceled)
+ return;
+ }
}
+ // Not responding, stop it
+ m_process.Kill();
throw new Exception("Process timed out!");
}
@@ -119,13 +166,27 @@ namespace Duplicati.Service
m_thread.Join();
}
- public void Stop()
+ public void Stop(bool force = true)
{
- m_terminate = true;
- var p = m_process;
- if (p != null)
- p.Kill();
- Wait();
+ if (force)
+ {
+ m_terminate = true;
+ var p = m_process;
+ if (p != null)
+ p.Kill();
+ }
+ else
+ {
+ m_softstop = true;
+ lock (m_writelock)
+ {
+ if (m_process != null)
+ {
+ m_process.StandardInput.WriteLine("shutdown");
+ m_process.StandardInput.Flush();
+ }
+ }
+ }
}
public void Dispose()