Изящно завершить процесс в Windows - PullRequest
1 голос
/ 10 марта 2019

Я пишу серверное приложение на Go и использую оболочку для запуска его в качестве службы Windows.

Необходимо аккуратно завершить работу сервера (чтобы правильно закрыть ресурсы и соединения), ив UNIX это будет обрабатываться через сигнал SIGTERM.Ничего страшного.

Хотя в Windows все выглядит совсем иначе.Я вижу в этом руководстве , что сигналы фактически существуют в окнах (?), И SIGTERM определен, хотя на других страницах указано , что они не , или используют другие механизмы, такие как WM_CLOSE.

Каков предпочтительный способ заставить безголовый процесс грациозно завершиться?Как это должно быть реализовано в Go?

Сервер спроектирован так, чтобы быть мультиплатформенным, поэтому наиболее стандартный способ сделать это предпочтительнее.

Ответы [ 2 ]

0 голосов
/ 11 марта 2019

Способ go инициирования отмены задачи / службы заключается в использовании пакета context.Context .

Поэтому, если вы хотите, чтобы обработчик сигнала инициировал закрытиеcontext.Context:

func registerSigHandler() context.Context {
        sigCh := make(chan os.Signal, 1)
        signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

        rootCtx := context.Background()
        taskCtx, cancelFn := context.WithCancel(rootCtx)

        go func() {
                sig := <-sigCh
                log.Println("received signal:", sig)

                // let sub-task know to wrap up: cancel taskCtx
                cancelFn()
        }()

        return taskCtx
}

задачи, а затем передать возвращенное taskCtx вашему рабочему заданию для прослушивания.

select {
    case <-taskCtx.Done():
        // context was canceled
    default: // poll - rather than block in this example
}

Playground source-code .

Выход:

2019/03/10 19:18:51 Worker PID: 33186
2019/03/10 19:18:51 Will terminate on these signals: interrupt terminated
2019/03/10 19:18:51 2019-03-10 19:18:51.018962 -0400 EDT m=+0.001727305
2019/03/10 19:18:52 2019-03-10 19:18:52.022782 -0400 EDT m=+1.005517010
2019/03/10 19:18:53 2019-03-10 19:18:53.019925 -0400 EDT m=+2.002630457

$ kill -INT 33186

2019/03/10 19:18:53 received signal: interrupt
2019/03/10 19:18:53 task context terminated reason: context canceled
2019/03/10 19:18:53 wrapping up task...
2019/03/10 19:18:53 workerTask() exited cleanly
2019/03/10 19:18:53 main exited cleanly

РЕДАКТИРОВАТЬ:

Я проверил это на Windows 10 и очистка запускается, когдаCtrl-C выдается из той же консоли.Не уверен, как отправлять сигналы извне в Windows - что может быть оригинальной проблемой ОП.Использование скажем killtask /F /PID 33186 действительно убило бы процесс без запуска какого-либо обработчика сигнала.

0 голосов
/ 11 марта 2019

Если вы используете какую-либо форму веб-сервисов, может быть лучше использовать сам веб-сервис для инициирования выключения, так как отслеживание PIDS для сигналов может запутаться.

Чтобы остановить веб-сервис http, просто добавьте маршрут следующим образом:

http.HandleFunc("/shutdown",
        func(w http.ResponseWriter, r *http.Request) {
            // stops server - may want to add admin credentials check here!
            srv.Shutdown(context.Background())
        })

Детская площадка Исходный код пример.

2019/03/10 16:58:15 Listening on: :8080

$ curl 'localhost:8080/shutdown'

2019/03/10 17:04:17 Listening on: :8080
2019/03/10 17:04:19 exited cleanly
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...