Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

service.cpp

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2005 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
00027 */
00028 
00029 #include "precomp.h"
00030 #include "service.h"
00031 #include "file.h"
00032 #include "string_help.h"
00033 #include "exception.h"
00034 #include "thread.h"
00035 #include <iostream>
00036 #ifndef WIN32
00037 #include <signal.h>
00038 #endif
00039 
00041 // CL_Service Construction:
00042 
00043 CL_Service::CL_Service(const CL_String &service_name)
00044 : service_name(service_name)
00045 {
00046         if (instance != 0)
00047                 throw CL_Exception(TEXT("More than one instance of CL_Service not allowed"));
00048         instance = this;
00049 }
00050 
00051 CL_Service::~CL_Service()
00052 {
00053         instance = 0;
00054 }
00055 
00057 // CL_Service Attributes:
00058 
00060 // CL_Service Operations:
00061 
00062 int CL_Service::main(int argc, char **argv)
00063 {
00064         std::vector<CL_String> args;
00065         for (int i=0; i<argc; i++)
00066                 args.push_back(argv[i]);
00067 
00068 #ifdef WIN32
00069         if (argc == 2 && args[1] == TEXT("-debug"))
00070         {
00071                 SetConsoleCtrlHandler(&CL_Service::control_handler, TRUE);
00072                 service_run(args);
00073                 return 0;
00074         }
00075         else
00076         {
00077                 std::cout << "Service parameters:" << std::endl;
00078 //              std::cout << "  -install            - Install service" << std::endl;
00079 //              std::cout << "  -uninstall          - Remove the service" << std::endl;
00080                 std::cout << "  -debug              - Debug service" << std::endl;
00081                 std::cout << std::endl;
00082                 std::cout << "StartServiceCtrlDispatcher being called." << std::endl;
00083                 std::cout << "This may take several seconds. Please wait." << std::endl;
00084 
00085                 SERVICE_TABLE_ENTRY dispatch_table[] =
00086                 {
00087                         { (LPTSTR) service_name.c_str(), (LPSERVICE_MAIN_FUNCTION) &CL_Service::service_thread_main },
00088                         { 0, 0 }
00089                 };
00090 
00091                 BOOL start_service = StartServiceCtrlDispatcher(dispatch_table);
00092                 if (start_service == FALSE)
00093                         return 0;
00094 
00095                 service_run(args);
00096                 return 0;
00097         }
00098 #else
00099         if (argc >= 3 && args[1] == TEXT("-daemon"))
00100         {
00101                 try
00102                 {
00103                         CL_File file(args[2], CL_File::create_always);
00104 
00105                         struct sigaction action;
00106                         memset(&action, 0, sizeof(struct sigaction));
00107                         action.sa_handler = &CL_Service::sig_term;
00108                         sigaction(SIGTERM, &action, 0);
00109                         memset(&action, 0, sizeof(struct sigaction));
00110                         action.sa_handler = &CL_Service::sig_hup;
00111                         sigaction(SIGHUP, &action, 0);
00112 
00113                         int pid = fork();
00114                         if (pid)
00115                         {
00116                                 CL_StringA str_pid = CL_StringHelp::int_to_local8(pid);
00117                                 file.write(str_pid.c_str(), str_pid.length());
00118                                 file.write("\n", 1);
00119                                 return pid;
00120                         }
00121                         else
00122                         {
00123                                 file.close();
00124                                 close(0);
00125                                 close(1);
00126                                 close(2);
00127 
00128                                 // Starting service in seperate thread to avoid
00129                                 // signals sent to this pid causing EINTR errors
00130                                 // randomly in the service itself.
00131                                 CL_Thread thread;
00132                                 thread.start(this, &CL_Service::service_thread_main, args);
00133                                 while (true)
00134                                 {
00135                                         try
00136                                         {
00137                                                 if (stop_event.wait())
00138                                                         break;
00139                                         }
00140                                         catch (CL_Exception e)
00141                                         {
00142                                         }
00143                                 }
00144                                 thread.join();
00145                                 return 0;
00146                         }
00147                 }
00148                 catch (CL_Exception e)
00149                 {
00150                         std::cout << "Unhandled exception: " << e.message.c_str() << std::endl;
00151                 }
00152         }
00153         else if (argc == 2 && args[1] == TEXT("-debug"))
00154         {
00155                 struct sigaction action;
00156                 memset(&action, 0, sizeof(struct sigaction));
00157                 action.sa_handler = &CL_Service::sig_term;
00158                 sigaction(SIGTERM, &action, 0);
00159                 memset(&action, 0, sizeof(struct sigaction));
00160                 action.sa_handler = &CL_Service::sig_hup;
00161                 sigaction(SIGHUP, &action, 0);
00162                 memset(&action, 0, sizeof(struct sigaction));
00163                 action.sa_handler = &CL_Service::sig_term;
00164                 sigaction(SIGINT, &action, 0);
00165                 
00166                 // Starting service in seperate thread to avoid
00167                 // signals sent to this pid causing EINTR errors
00168                 // randomly in the service itself.
00169                 CL_Thread thread;
00170                 thread.start(this, &CL_Service::service_thread_main, args);
00171                 while (true)
00172                 {
00173                         try
00174                         {
00175                                 if (stop_event.wait())
00176                                         break;
00177                         }
00178                         catch (CL_Exception e)
00179                         {
00180                         }
00181                 }
00182                 thread.join();
00183                 return 0;
00184         }
00185         else
00186         {
00187                 std::cout << "Service parameters:" << std::endl;
00188                 std::cout << "  -daemon <pidfile>   - Start service as a unix daemon" << std::endl;
00189                 std::cout << "  -debug              - Debug service" << std::endl;
00190                 return 0;
00191         }
00192 #endif
00193 }
00194 
00196 // CL_Service Implementation:
00197 
00198 #ifdef WIN32
00199 void CL_Service::service_thread_main(DWORD argc, LPTSTR *argv)
00200 {
00201         if (instance == 0)
00202                 return;
00203 
00204         std::vector<CL_String> args;
00205         for (int i=0; i<argc; i++)
00206                 args.push_back(argv[i]);
00207 
00208         instance->service_run(args);
00209 }
00210 
00211 BOOL CL_Service::control_handler(DWORD ctrl_type)
00212 {
00213         if (instance == 0)
00214                 return FALSE;
00215 
00216         switch(ctrl_type)
00217         {
00218         case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
00219         case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in debug mode
00220                 std::cout << "Stopping service" << std::endl;
00221                 instance->stop_event.set();
00222                 return TRUE;
00223 
00224         default:
00225                 std::cout << "Service::ControlHandler got unknown control type" << std::endl;
00226         }
00227         return FALSE;
00228 }
00229 #else
00230 void CL_Service::service_thread_main(std::vector<CL_String> args)
00231 {
00232         service_run(args);
00233 }
00234 
00235 void CL_Service::sig_term(int signal)
00236 {
00237         if (instance)
00238                 instance->stop_event.set();
00239 }
00240 
00241 void CL_Service::sig_hup(int signal)
00242 {
00243         if (instance)
00244                 instance->reload_event.set();
00245 }
00246 #endif
00247 
00248 CL_Service *CL_Service::instance = 0;

Generated on Sat Feb 19 22:51:16 2005 for npcore by  doxygen 1.4.1