⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winservice.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * winservice.c : Implementation of Windows Service support * * ==================================================================== * Copyright (c) 2000-2006 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#define APR_WANT_STRFUNC#include <apr_want.h>#include <apr_errno.h>#include "svn_error.h"#include "svn_private_config.h"#include "winservice.h"/*Design Notes------------The code in this file allows svnserve to run as a Windows service.Windows Services are only supported on operating systems derivedfrom Windows NT, which is basically all modern versions of Windows(2000, XP, Server, Vista, etc.) and excludes the Windows 9x line.Windows Services are processes that are started and controlled bythe Service Control Manager.  When the SCM wants to start a service,it creates the process, then waits for the process to connect tothe SCM, so that the SCM and service process can communicate.This is done using the StartServiceCtrlDispatcher function.In order to minimize changes to the svnserve startup logic, thisimplementation differs slightly from most service implementations.In most services, main() immediately calls StartServiceCtrlDispatcher,which does not return control to main() until the SCM sends the"stop" request to the service, and the service stops.Installing the Service----------------------Installation is beyond the scope of source code comments.  Thereis a separate document that describes how to install and uninstallthe service.  Basically, you create a Windows Service, give it abinary path that points to svnserve.exe, and make sure that youspecify --service on the command line.Starting the Service--------------------First, the SCM decides that it wants to start a service.  It createsthe process for the service, passing it the command-line that isstored in the service configuration (stored in the registry).Next, main() runs.  The command-line should contain the --serviceargument, which is the hint that svnserve is running under the SCM,not as a standalone process.  main() calls winservice_start().winservice_start() creates an event object (winservice_start_event),and creates and starts a separate thread, the "dispatcher" thread.winservice_start() then waits for either winservice_start_eventto fire (meaning: "the dispatcher thread successfully connectedto the SCM, and now the service is starting") or for the dispatcherthread to exit (meaning: "failed to connect to SCM").If the dispatcher thread quit, then winservice_start returns an error.If the start event fired, then winservice_start returns a success code(SVN_NO_ERROR).  At this point, the service is now in the "starting"state, from the perspective of the SCM.  winservice_start also registersan atexit handler, which handles cleaning up some of the service logic,as explained below in "Stopping the Service".Next, control returns to main(), which performs the usual startuplogic for svnserve.  Mostly, it creates the listener socket.  Ifmain() was able to start the service, then it calls the functionwinservice_running().winservice_running() informs the SCM that the service has finishedstarting, and is now in the "running" state.  main() then does itswork, accepting client sockets and processing SVN requests.Stopping the Service--------------------At some point, the SCM will decide to stop the service, either becausean administrator chose to stop the service, or the system is shuttingdown.  To do this, the SCM calls winservice_handler() with the SERVICE_CONTROL_STOP control code.  When this happens,winservice_handler() will inform the SCM that the service is nowin the "stopping" state, and will call winservice_notify_stop().winservice_notify_stop() is responsible for cleanly shutting down thesvnserve logic (waiting for client requests to finish, stopping databaseaccess, etc.).  Right now, all it does is close the listener socket,which causes the apr_socket_accept() call in main() to fail.  main()then calls exit(), which processes all atexit() handlers, whichresults in winservice_stop() being called.winservice_stop() notifies the SCM that the service is now stopped,and then waits for the dispatcher thread to exit.  Because all servicesin the process have now stopped, the call to StartServiceCtrlDispatcher(in the dispatcher thread) finally returns, and winservice_stop() returns,and the process finally exits.*/#ifdef WIN32#include <assert.h>#include <winsvc.h>/* This is just a placeholder, and doesn't actually constrain the  service name.  You have to provide *some* service name to the SCM  API, but for services that are marked SERVICE_WIN32_OWN_PROCESS (as  is the case for svnserve), the service name is ignored.  It *is*  relevant for service binaries that run more than one service in a  single process. */#define WINSERVICE_SERVICE_NAME "svnserve"/* Win32 handle to the dispatcher thread. */static HANDLE winservice_dispatcher_thread = NULL;/* Win32 event handle, used to notify winservice_start() that we have   successfully connected to the SCM. */static HANDLE winservice_start_event = NULL;/* RPC handle that allows us to notify the SCM of changes in our   service status. */static SERVICE_STATUS_HANDLE winservice_status_handle = NULL;/* Our current idea of the service status (stopped, running, controls   accepted, exit code, etc.) */static SERVICE_STATUS winservice_status;#ifdef SVN_DEBUGstatic void dbg_print(const char* text){  OutputDebugStringA(text);}#else/* Make sure dbg_print compiles to nothing in release builds. */#define dbg_print(text)#endifstatic void winservice_atexit(void);/* Notifies the Service Control Manager of the current state of the   service. */static voidwinservice_update_state(void){  if (winservice_status_handle != NULL)    {      if (!SetServiceStatus(winservice_status_handle, &winservice_status))        {          dbg_print("SetServiceStatus - FAILED\r\n");        }    }}/* This function cleans up state associated with the service support.   If the dispatcher thread handle is non-NULL, then this function   will wait for the dispatcher thread to exit. */static voidwinservice_cleanup(void){  if (winservice_start_event != NULL)    {      CloseHandle(winservice_start_event);      winservice_start_event = NULL;    }  if (winservice_dispatcher_thread != NULL)    {      dbg_print("winservice_cleanup:"                " waiting for dispatcher thread to exit\r\n");      WaitForSingleObject(winservice_dispatcher_thread, INFINITE);      CloseHandle(winservice_dispatcher_thread);      winservice_dispatcher_thread = NULL;    }}/* The SCM invokes this function to cause state changes in the   service. */static void WINAPIwinservice_handler(DWORD control){  switch (control)    {    case SERVICE_CONTROL_INTERROGATE:      /* The SCM just wants to check our state.  We are required to         call SetServiceStatus, but we don't need to make any state         changes. */      dbg_print("SERVICE_CONTROL_INTERROGATE\r\n");      winservice_update_state();      break;    case SERVICE_CONTROL_STOP:      dbg_print("SERVICE_CONTROL_STOP\r\n");      winservice_status.dwCurrentState = SERVICE_STOP_PENDING;      winservice_update_state();      winservice_notify_stop();      break;    }}/* This is the "service main" routine (in the Win32 terminology).   Normally, this function (thread) implements the "main" loop of a   service.  However, in order to minimize changes to the svnserve   main() function, this function is running in a different thread,   and main() is blocked in winservice_start(), waiting for   winservice_start_event.  So this function (thread) only needs to   signal that event to "start" the service.   If this function succeeds, it signals winservice_start_event, which   wakes up the winservice_start() frame that is blocked. */static void WINAPIwinservice_service_main(DWORD argc, LPTSTR *argv){  DWORD error;  assert(winservice_start_event != NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -