summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/win32/winsvc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/src/win32/winsvc.c')
-rw-r--r--fluent-bit/src/win32/winsvc.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/fluent-bit/src/win32/winsvc.c b/fluent-bit/src/win32/winsvc.c
new file mode 100644
index 000000000..9e0942ee5
--- /dev/null
+++ b/fluent-bit/src/win32/winsvc.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2020 The Fluent Bit Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Windows.h>
+#include <Shlwapi.h>
+
+struct flb_config;
+extern struct flb_config *config;
+extern int flb_engine_exit(struct flb_config*);
+extern int flb_main(int, char**);
+
+/* Windows Service utils */
+#define svc_name "fluent-bit"
+static SERVICE_STATUS_HANDLE hstatus;
+static int win32_argc;
+static char **win32_argv;
+
+/*
+ * A Windows Service uses 'C:\Windows\System32' as working directory
+ * by default. Here we use a more intuitive default path (where
+ * fluent-bit.exe exists).
+ */
+static int update_default_workdir(void)
+{
+ char path[MAX_PATH];
+
+ if (win32_argc < 1) {
+ return -1;
+ }
+
+ if (strcpy_s(path, MAX_PATH, win32_argv[0])) {
+ return -1;
+ }
+
+ if (!PathRemoveFileSpecA(path)) {
+ return -1;
+ }
+
+ if (!SetCurrentDirectoryA(path)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static void svc_notify(DWORD status)
+{
+ SERVICE_STATUS ss;
+
+ ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ ss.dwCurrentState = status;
+ ss.dwWin32ExitCode = NO_ERROR;
+ ss.dwServiceSpecificExitCode = NO_ERROR;
+ ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ ss.dwWaitHint = 30000;
+ ss.dwCheckPoint = 0;
+
+ /*
+ * According to MSDN (SetServiceStatus), accepting control on
+ * SERVICE_START_PENDING can crash the service.
+ */
+ if (status == SERVICE_START_PENDING) {
+ ss.dwControlsAccepted = 0;
+ }
+
+ SetServiceStatus(hstatus, &ss);
+}
+
+static void WINAPI svc_handler(DWORD ctrl)
+{
+ switch (ctrl)
+ {
+ case SERVICE_CONTROL_STOP:
+ svc_notify(SERVICE_STOP_PENDING);
+ flb_engine_exit(config);
+ return;
+ default:
+ break;
+ }
+}
+
+static void WINAPI svc_main(DWORD svc_argc, LPTSTR *svc_argv)
+{
+ hstatus = RegisterServiceCtrlHandler(svc_name, svc_handler);
+ if (!hstatus) {
+ return;
+ }
+
+ update_default_workdir();
+
+ svc_notify(SERVICE_START_PENDING);
+ flb_main(win32_argc, win32_argv);
+ svc_notify(SERVICE_STOPPED);
+}
+
+/*
+ * Notify SCM that Fluent Bit is running.
+ *
+ * Note: Call this function in the main execution flow (immediately
+ * before the engine is starting).
+ */
+void win32_started(void)
+{
+ if (hstatus) {
+ svc_notify(SERVICE_RUNNING);
+ }
+}
+
+static const SERVICE_TABLE_ENTRY svc_table[] = {
+ {svc_name, svc_main},
+ {NULL, NULL}
+};
+
+int win32_main(int argc, char **argv)
+{
+ win32_argc = argc;
+ win32_argv = argv;
+
+ if (StartServiceCtrlDispatcher(svc_table)) {
+ return 0;
+ }
+
+ if (GetLastError() != ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
+ return -1;
+ }
+
+ /*
+ * If we cannot connect to SCM, we assume that "fluent-bit.exe"
+ * was invoked from the command line.
+ */
+ return flb_main(argc, argv);
+}