Skip to content

Commit f134d5d

Browse files
author
Richard Jones
committed
added Windows Service mode for roundup-server...
...when daemonification is attempted on Windows.
1 parent 9394815 commit f134d5d

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ Feature:
6666
- extended date syntax to make range searches even more useful
6767
- SMTP login and TLS support added (sf bug 710853 with extras ;)
6868
Note: requires python 2.2+
69+
- added Windows Service mode for roundup-server when daemonification is
70+
attempted on Windows.
6971

7072
Fixed:
7173
- applied unicode patch. All data is stored in utf-8. Incoming messages

doc/index.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Gordon McMillan,
7272
Patrick Ohly,
7373
Luke Opperman,
7474
Will Partain,
75+
Ewout Prangsma,
7576
Bernhard Reiter,
7677
John P. Rouillard,
7778
Florian Schulze,

roundup/scripts/roundup_server.py

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
#
1717
""" HTTP Server that serves roundup.
1818
19-
$Id: roundup_server.py,v 1.23 2003-04-24 07:19:02 richard Exp $
19+
$Id: roundup_server.py,v 1.24 2003-05-09 02:02:40 richard Exp $
2020
"""
2121

2222
# python version check
2323
from roundup import version_check
2424

2525
import sys, os, urllib, StringIO, traceback, cgi, binascii, getopt, imp
26-
import BaseHTTPServer
26+
import BaseHTTPServer, socket
2727

2828
# Roundup modules of use here
2929
from roundup.cgi import cgitb, client
@@ -204,6 +204,99 @@ def inner_run_cgi(self):
204204
c = tracker.Client(tracker, self, env)
205205
c.main()
206206

207+
208+
try:
209+
import win32serviceutil
210+
except:
211+
RoundupService = None
212+
else:
213+
# allow the win32
214+
import win32service
215+
import win32event
216+
from win32event import *
217+
from win32file import *
218+
219+
SvcShutdown = "ServiceShutdown"
220+
221+
class RoundupService(win32serviceutil.ServiceFramework,
222+
BaseHTTPServer.HTTPServer):
223+
''' A Roundup standalone server for Win32 by Ewout Prangsma
224+
'''
225+
_svc_name_ = "Roundup Bug Tracker"
226+
_svc_display_name_ = "Roundup Bug Tracker"
227+
address = ('', 8888)
228+
def __init__(self, args):
229+
win32serviceutil.ServiceFramework.__init__(self, args)
230+
BaseHTTPServer.HTTPServer.__init__(self, self.address,
231+
RoundupRequestHandler)
232+
233+
# Create the necessary NT Event synchronization objects...
234+
# hevSvcStop is signaled when the SCM sends us a notification
235+
# to shutdown the service.
236+
self.hevSvcStop = win32event.CreateEvent(None, 0, 0, None)
237+
238+
# hevConn is signaled when we have a new incomming connection.
239+
self.hevConn = win32event.CreateEvent(None, 0, 0, None)
240+
241+
# Hang onto this module for other people to use for logging
242+
# purposes.
243+
import servicemanager
244+
self.servicemanager = servicemanager
245+
246+
def SvcStop(self):
247+
# Before we do anything, tell the SCM we are starting the
248+
# stop process.
249+
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
250+
win32event.SetEvent(self.hevSvcStop)
251+
252+
def SvcDoRun(self):
253+
try:
254+
self.serve_forever()
255+
except SvcShutdown:
256+
pass
257+
258+
def get_request(self):
259+
# Call WSAEventSelect to enable self.socket to be waited on.
260+
WSAEventSelect(self.socket, self.hevConn, FD_ACCEPT)
261+
while 1:
262+
try:
263+
rv = self.socket.accept()
264+
except socket.error, why:
265+
if why[0] != WSAEWOULDBLOCK:
266+
raise
267+
# Use WaitForMultipleObjects instead of select() because
268+
# on NT select() is only good for sockets, and not general
269+
# NT synchronization objects.
270+
rc = WaitForMultipleObjects((self.hevSvcStop, self.hevConn),
271+
0, INFINITE)
272+
if rc == WAIT_OBJECT_0:
273+
# self.hevSvcStop was signaled, this means:
274+
# Stop the service!
275+
# So we throw the shutdown exception, which gets
276+
# caught by self.SvcDoRun
277+
raise SvcShutdown
278+
# Otherwise, rc == WAIT_OBJECT_0 + 1 which means
279+
# self.hevConn was signaled, which means when we call
280+
# self.socket.accept(), we'll have our incoming connection
281+
# socket!
282+
# Loop back to the top, and let that accept do its thing...
283+
else:
284+
# yay! we have a connection
285+
# However... the new socket is non-blocking, we need to
286+
# set it back into blocking mode. (The socket that accept()
287+
# returns has the same properties as the listening sockets,
288+
# this includes any properties set by WSAAsyncSelect, or
289+
# WSAEventSelect, and whether its a blocking socket or not.)
290+
#
291+
# So if you yank the following line, the setblocking() call
292+
# will be useless. The socket will still be in non-blocking
293+
# mode.
294+
WSAEventSelect(rv[0], self.hevConn, 0)
295+
rv[0].setblocking(1)
296+
break
297+
return rv
298+
299+
207300
def usage(message=''):
208301
if message:
209302
message = _('Error: %(error)s\n\n')%{'error': message}
@@ -213,7 +306,9 @@ def usage(message=''):
213306
-n: sets the host name
214307
-p: sets the port to listen on
215308
-l: sets a filename to log to (instead of stdout)
216-
-d: daemonize, and write the server's PID to the nominated file
309+
-d: run the server in the background and on UN*X write the server's PID
310+
to the nominated file. Note: on Windows the PID argument is needed,
311+
but ignored.
217312
218313
name=tracker home
219314
Sets the tracker home(s) to use. The name is how the tracker is
@@ -340,11 +435,16 @@ def run():
340435

341436
# fork?
342437
if pidfile:
343-
if not hasattr(os, 'fork'):
438+
if RoundupService:
439+
# don't do any other stuff
440+
RoundupService.address = address
441+
return win32serviceutil.HandleCommandLine(RoundupService)
442+
elif not hasattr(os, 'fork'):
344443
print "Sorry, you can't run the server as a daemon on this" \
345444
'Operating System'
346445
sys.exit(0)
347-
daemonize(pidfile)
446+
else:
447+
daemonize(pidfile)
348448

349449
# redirect stdout/stderr to our logfile
350450
if logfile:

0 commit comments

Comments
 (0)