Служба Windows не может быть остановлена - PullRequest
0 голосов
/ 28 июня 2018

У меня проблема со службой Windows. Иногда служба не может быть остановлена ​​и зависает в рабочем состоянии) после команды запуска с сообщением: The service cannot accept control messages at this time

Упрощенная реализация сервиса:

using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class Service : ServiceBase
    {
        protected object SyncRoot { get; } = new object();
        protected override void OnStart(string[] args)
        {
            lock (SyncRoot)
            {
                var task = PerformHealthCheck();

                while (!task.Wait(10000))
                {
                    RequestAdditionalTime(10000);
                }

                Task.Factory.StartNew(() =>
                {
                    //Some logic to start worker threads and initialize some startup processes
                    //All workers threads actually successfully executed.
                }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
            }
        }

        protected override void OnStop()
        {
            //Code is not reachable sometimes
            lock (SyncRoot)
            {
                //Some stop logic
            }
        }

        private static async Task PerformHealthCheck()
        {
            int status = 0;
            do
            {
                status = CheckStatus();
                if (status == 0)
                {
                    await Task.Delay(20000);
                }
            }
            while (status == 0);
        }

        private static int CheckStatus()
        {
            //Calculating HealthCheck status
            return 0;
        }
    }
}

Логика создания:

internal static class Program
{
    private static void Main(string[] args)
    {
        ServiceBase.Run(new Service());
    }
}

Метод OnStart успешно выполняется до конца, а метод OnStop даже не срабатывает. Я вижу статус сервиса в WinDbg следующим образом:

16 serviceType
4 currentState
5 controlsAccepted
0 win32ExitCode
0 serviceSpecificExitCode
0 checkPoint
0 waitHint

Итак, насколько я понимаю, служба находится в состоянии «Выполнено» и получила команду остановки, но не выполнила ее (я вижу это по журналам). Я не понимаю, что может помешать службе выполнять метод OnStop. Команда «Пуск» отображается в окне событий Windows, но команда «Стоп» отсутствует.

Другая информация:

  • .NET 4.5 Framework
  • Windows Server 2012-2016

1 Ответ

0 голосов
/ 28 июня 2018

В вашем примере PerformHealthCheck() будет работать неопределенно долго. Таким образом, ваш OnStart никогда не заканчивается. Не знаю, только ли это из-за вашего упрощенного примера.

Однако, вы что-то регистрируете, когда это происходит? Например, зарегистрируйте конец метода OnStart и убедитесь, что при возникновении проблемы OnStart фактически завершился. В своем коде-комментарии вы пишете //Code is not reachabl.., вы тоже что-то там регистрируете? Или в замке?

Кстати, блокировка запуска и остановки может показаться хорошей идеей для синхронизации, но как пользователь, если я хочу остановить службу, я действительно хочу ее остановить. Независимо от того, все еще в состоянии запуска. На самом деле, если служба не отвечает на команду остановки, я подозреваю, что в 90% случаев диспетчер задач в любом случае является следующей остановкой ... Разве не лучше, если вы попытаетесь переписать логику останова таким образом, чтобы он всегда просто выполняет и ломает все, что может? Это, вероятно, решит вашу проблему, а также улучшит опыт imo.

Редактировать, кажется, что блокировки на самом деле ничего не делают (по крайней мере, если они используются только здесь, а не для блокировки чего-либо в другом месте) ОС не будет передавать команду OnStop, если она все еще StartPending .. :

Возможно ли, что это происходит, когда запуск просто занимает LONG и остановка вызывается до того, как запуск завершится? Смотрите этот пример:

class logger
{
    static readonly object _logSync = new object();

    public void Log(string message)
    {
        var m = $"{DateTime.Now.ToString("HH:mm:ss")}; {message}{Environment.NewLine}";
        lock(_logSync)
        {
            File.AppendAllText(@"C:\temp\test.txt", m);
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        ServiceBase.Run(new TestHangService());
    }
}
class TestHangService : ServiceBase
{
    private logger _log;

    public TestHangService()
    {
        _log = new logger();
    }

    protected override void OnStart(string[] args)
    {
        _log.Log("OnStart");
        Thread.Sleep(30 * 1000);
        _log.Log("OnStart exit");
    }

    protected override void OnStop()
    {
        _log.Log("OnStop");
    }
}

Тогда

C:\WINDOWS\system32>sc create DeleteMe binpath="C:\testprojects\TestService\TestService\bin\Debug\TestService.exe"
[SC] CreateService SUCCESS

C:\WINDOWS\system32>sc start deleteMe

SERVICE_NAME: deleteMe
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x7d0
    PID                : 27376
    FLAGS              :

C:\WINDOWS\system32>echo "executed directly after starting"
"executed directly after starting"

C:\WINDOWS\system32>sc stop deleteMe

SERVICE_NAME: deleteMe
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 2  START_PENDING
                            (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

C:\WINDOWS\system32>echo "waiting for 30 sec"
"waiting for 30 sec"

C:\WINDOWS\system32>sc stop deleteMe
[SC] ControlService FAILED 1061:

The service cannot accept control messages at this time.

который регистрирует:

18: 32: 20; OnStart

18: 32: 50; Выход при запуске

примечание не остановлено

Кажется, это не восстановится (что удивило меня) даже через 10 минут:

C:\WINDOWS\system32>sc query deleteme

SERVICE_NAME: deleteme
    TYPE               : 10  WIN32_OWN_PROCESS
    STATE              : 4  RUNNING
                            (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

C:\WINDOWS\system32>sc stop deleteme
[SC] ControlService FAILED 1061:

The service cannot accept control messages at this time.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...