Skip to content

Commit 0232b6a

Browse files
author
Alexander Smishlajev
committed
windows service part rewritten to take in account command line options;
require logfile for windows service; log service startup and shutdown in windows event log
1 parent d8bdf15 commit 0232b6a

File tree

1 file changed

+59
-77
lines changed

1 file changed

+59
-77
lines changed

roundup/scripts/roundup_server.py

Lines changed: 59 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
"""Command-line script that runs a server over roundup.cgi.client.
1919
20-
$Id: roundup_server.py,v 1.68 2004-10-29 17:57:17 a1s Exp $
20+
$Id: roundup_server.py,v 1.69 2004-10-29 20:39:31 a1s Exp $
2121
"""
2222
__docformat__ = 'restructuredtext'
2323

@@ -428,88 +428,48 @@ class ThreadingServer(SocketServer.ThreadingMixIn,
428428
class SvcShutdown(Exception):
429429
pass
430430

431-
class RoundupService(win32serviceutil.ServiceFramework,
432-
BaseHTTPServer.HTTPServer):
433-
''' A Roundup standalone server for Win32 by Ewout Prangsma
434-
'''
431+
class RoundupService(win32serviceutil.ServiceFramework):
432+
435433
_svc_name_ = "Roundup Bug Tracker"
436434
_svc_display_name_ = "Roundup Bug Tracker"
437-
def __init__(self, args):
438-
# redirect stdout/stderr to our logfile
439-
if LOGFILE:
440-
# appending, unbuffered
441-
sys.stdout = sys.stderr = open(LOGFILE, 'a', 0)
442-
win32serviceutil.ServiceFramework.__init__(self, args)
443-
BaseHTTPServer.HTTPServer.__init__(self, self.address,
444-
RoundupRequestHandler)
445-
446-
# Create the necessary NT Event synchronization objects...
447-
# hevSvcStop is signaled when the SCM sends us a notification
448-
# to shutdown the service.
449-
self.hevSvcStop = win32event.CreateEvent(None, 0, 0, None)
450-
451-
# hevConn is signaled when we have a new incomming connection.
452-
self.hevConn = win32event.CreateEvent(None, 0, 0, None)
453-
454-
# Hang onto this module for other people to use for logging
455-
# purposes.
435+
436+
running = 0
437+
server = None
438+
439+
def SvcDoRun(self):
456440
import servicemanager
457-
self.servicemanager = servicemanager
441+
self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
442+
config = ServerConfig()
443+
(optlist, args) = config.getopt(sys.argv[1:])
444+
if not config["LOGFILE"]:
445+
servicemanager.LogMsg(servicemanager.EVENTLOG_ERROR_TYPE,
446+
servicemanager.PYS_SERVICE_STOPPED,
447+
(self._svc_display_name_, "\r\nMissing logfile option"))
448+
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
449+
return
450+
self.server = config.get_server()
451+
self.running = 1
452+
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
453+
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
454+
servicemanager.PYS_SERVICE_STARTED, (self._svc_display_name_,
455+
" at %s:%s" % (config["HOST"], config["PORT"])))
456+
while self.running:
457+
self.server.handle_request()
458+
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
459+
servicemanager.PYS_SERVICE_STOPPED,
460+
(self._svc_display_name_, ""))
461+
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
458462

459463
def SvcStop(self):
460-
# Before we do anything, tell the SCM we are starting the
461-
# stop process.
464+
self.running = 0
465+
# make dummy connection to self to terminate blocking accept()
466+
addr = self.server.socket.getsockname()
467+
if addr[0] == "0.0.0.0":
468+
addr = ("127.0.0.1", addr[1])
469+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
470+
sock.connect(addr)
471+
sock.close()
462472
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
463-
win32event.SetEvent(self.hevSvcStop)
464-
465-
def SvcDoRun(self):
466-
try:
467-
self.serve_forever()
468-
except SvcShutdown:
469-
pass
470-
471-
def get_request(self):
472-
# Call WSAEventSelect to enable self.socket to be waited on.
473-
win32file.WSAEventSelect(self.socket, self.hevConn,
474-
win32file.FD_ACCEPT)
475-
while 1:
476-
try:
477-
rv = self.socket.accept()
478-
except socket.error, why:
479-
if why[0] != win32file.WSAEWOULDBLOCK:
480-
raise
481-
# Use WaitForMultipleObjects instead of select() because
482-
# on NT select() is only good for sockets, and not general
483-
# NT synchronization objects.
484-
rc = win32event.WaitForMultipleObjects(
485-
(self.hevSvcStop, self.hevConn),
486-
0, win32event.INFINITE)
487-
if rc == win32event.WAIT_OBJECT_0:
488-
# self.hevSvcStop was signaled, this means:
489-
# Stop the service!
490-
# So we throw the shutdown exception, which gets
491-
# caught by self.SvcDoRun
492-
raise SvcShutdown
493-
# Otherwise, rc == win32event.WAIT_OBJECT_0 + 1 which means
494-
# self.hevConn was signaled, which means when we call
495-
# self.socket.accept(), we'll have our incoming connection
496-
# socket!
497-
# Loop back to the top, and let that accept do its thing...
498-
else:
499-
# yay! we have a connection
500-
# However... the new socket is non-blocking, we need to
501-
# set it back into blocking mode. (The socket that accept()
502-
# returns has the same properties as the listening sockets,
503-
# this includes any properties set by WSAAsyncSelect, or
504-
# WSAEventSelect, and whether its a blocking socket or not.)
505-
#
506-
# So if you yank the following line, the setblocking() call
507-
# will be useless. The socket will still be in non-blocking
508-
# mode.
509-
win32file.WSAEventSelect(rv[0], self.hevConn, 0)
510-
rv[0].setblocking(1)
511-
break
512-
return rv
513473

514474
def usage(message=''):
515475
if RoundupService:
@@ -621,6 +581,28 @@ def run(port=undefined, success_message=None):
621581

622582
# if running in windows service mode, don't do any other stuff
623583
if ("-c", "") in optlist:
584+
# acquire command line options recognized by service
585+
short_options = "c:C:"
586+
long_options = ["config"]
587+
for (long_name, short_name) in config.OPTIONS.items():
588+
short_options += short_name
589+
long_name = long_name.lower().replace("_", "-")
590+
if short_name[-1] == ":":
591+
long_name += "="
592+
long_options.append(long_name)
593+
optlist = getopt.getopt(sys.argv[1:], short_options, long_options)[0]
594+
svc_args = []
595+
for (opt, arg) in optlist:
596+
if opt in ("-C", "-l"):
597+
# make sure file name is absolute
598+
svc_args.extend((opt, os.path.abspath(arg)))
599+
elif opt in ("--config", "--logfile"):
600+
# ditto, for long options
601+
svc_args.append("=".join(opt, os.path.abspath(arg)))
602+
elif opt != "-c":
603+
svc_args.extend(opt)
604+
RoundupService._exe_args_ = " ".join(svc_args)
605+
# pass the control to serviceutil
624606
win32serviceutil.HandleCommandLine(RoundupService,
625607
argv=sys.argv[:1] + args)
626608
return

0 commit comments

Comments
 (0)