[Mongrel] Patch to fix mongrel_service bugs with Windows Vista/2008 support and log file location

Daniel Gies daniel_gies at bigfix.com
Fri Sep 11 13:03:39 EDT 2009


Hello Mongrel users,

I¹m a software developer at BigFix ( http://www.bigfix.com ) and we use
Mongrel in one of our products.  We have made changes to the mongrel_service
component to address problems outlined in Mongrel tickets 44 and 54:
http://mongrel.rubyforge.org/ticket/44
http://mongrel.rubyforge.org/ticket/54

The modifications are as follows:
Change the way mongrel_service detects its runtime environment to use a
method compliant with the Windows Vista security model.  This modification
consists primarily of replacing elevated privilege code for process
inspection with a command-line argument.
Check for the ³-l² command line option and use that for the log file instead
of using a hard-coded location.  The ³-P² option was not implemented.

In accordance with term 2.a of the Ruby License (
http://www.ruby-lang.org/en/LICENSE.txt ), we are making our changes freely
available to the open source community.
The patch is based off of root/branches/stable_1-2/projects/mongrel_service
as of 2009-09-10, also known as mongrel_service 0.35.
If you would prefer to receive the patch in an email attachment please let
me know.
The patch is included below:

diff -r -u old/CHANGELOG new/CHANGELOG
--- old/CHANGELOG    2008-04-18 07:09:00.000000000 -0700
+++ new/CHANGELOG    2009-09-10 11:39:13.000000000 -0700
@@ -1,3 +1,8 @@
+* BigFix *
+    * Fixed issue with Windows Server 208 support by replacing detection of
parent
+      process with checking first argument "single".
+    * The option "-l LOGFILE" works now
+
 * 0.3.5 *
 
     * Wait longer for child process terminate properly (max 20 seconds).
Imported
diff -r -u old/lib/ServiceFB/ServiceFB.bas new/lib/ServiceFB/ServiceFB.bas
--- old/lib/ServiceFB/ServiceFB.bas    2007-09-10 21:38:00.000000000 -0700
+++ new/lib/ServiceFB/ServiceFB.bas    2009-09-10 11:39:12.000000000 -0700
@@ -258,23 +258,25 @@
         dim commandline as string
         dim param_line as string
         dim temp as string
+        dim logfile as string
         
         _dprint("_main()")
         
         '# debug dump of argc and argv
         dim idx as integer = 0
+        dim argskip as integer = 0
         for idx = 0 to (argc - 1)
             _dprint(str(idx) + ": " + *argv[idx])
         next idx
         
         '# retrieve all the information (mode, service name and command
line
-        _build_commandline(run_mode, service_name, commandline)
+        _build_commandline(run_mode, service_name, commandline, logfile,
argskip)
         service = _find_in_references(service_name)
         
         '# build parameter line (passed from SCM)
-        if (argc > 1) then
+        if (argc > argskip) then
             param_line = ""
-            for idx = 1 to (argc - 1)
+            for idx = argskip to (argc - 1)
                 temp = *argv[idx]
                 if (instr(temp, chr(32)) > 0) then
                     param_line += """" + temp + """"
@@ -561,10 +563,11 @@
     '# mode (if present)
     '# valid service name (after lookup in the table)
     '# command line to be passed to service
-    sub _build_commandline(byref mode as string, byref service_name as
string, byref commandline as string)
+    sub _build_commandline(byref mode as string, byref service_name as
string, byref commandline as string, byref logfile as string, byref idxskip
as integer)
         dim result_mode as string
         dim result_name as string
         dim result_cmdline as string
+        dim result_logfile as string
         dim service as ServiceProcess ptr
         dim idx as integer
         dim temp as string
@@ -607,6 +610,17 @@
                 result_name = ""
             end if
         end if
+        
+        '# check for log name
+        temp = command(idx)
+        if(temp = "-l") or (temp = "--log") then
+            idx += 1
+            result_logfile = command(idx)
+            idx += 1
+        end if
+        idxskip = idx
+        
+        _dprint("_build_commandline():result_logfile = "+result_logfile)
         
         result_cmdline = ""
         
@@ -628,6 +642,7 @@
         mode = result_mode
         service_name = result_name
         commandline = result_cmdline
+        logfile = result_logfile
     end sub
     
     
diff -r -u old/lib/ServiceFB/ServiceFB_Utils.bas
new/lib/ServiceFB/ServiceFB_Utils.bas
--- old/lib/ServiceFB/ServiceFB_Utils.bas    2008-04-17 18:59:00.000000000
-0700
+++ new/lib/ServiceFB/ServiceFB_Utils.bas    2009-09-10 11:39:12.000000000
-0700
@@ -80,27 +80,33 @@
         dim start_mode as string
         
         _dprint("ServiceController.RunMode()")
+        
+        '#_dprint("Modified to always RunAsService")
+        '#result = RunAsService
+        '#return result
         
         '# get this process PID
-        currPID = GetCurrentProcessId()
-        _dprint("CurrentPID: " + str(currPID))
+        '#currPID = GetCurrentProcessId()
+        '#_dprint("CurrentPID: " + str(currPID))
         
         '# get the parent PID
-        parent_pid = _parent_pid(currPID)
-        _dprint("ParentPID: " + str(parent_pid))
+        '#parent_pid = _parent_pid(currPID)
+        '#_dprint("ParentPID: " + str(parent_pid))
         
         '# now the the name
-        parent_name = _process_name(parent_pid)
-        if (parent_name = "<unknown>") then
-          parent_name = _process_name_dyn_psapi(parent_pid)
-        end if
-        _dprint("Parent Name: " + parent_name)
+        '#parent_name = _process_name(parent_pid)
+        '#if (parent_name = "<unknown>") then
+        '#  parent_name = _process_name_dyn_psapi(parent_pid)
+        '#end if
+        '#_dprint("Parent Name: " + parent_name)
+        
+        _dprint("command: "+command)
         
         '# this process started as service?
         '# that means his parent is services.exe
-        if (parent_name = "services.exe") then
-            result = RunAsService
-        else
+        '#if (parent_name = "services.exe") then
+        '#    result = RunAsService
+        '#else
             '# ok, it didn't start as service, analyze command line then
             start_mode = lcase(trim(command(1)))
             if (start_mode = "manage") then
@@ -109,12 +115,15 @@
             elseif (start_mode = "console") then
                 '# start ServiceController.Console()
                 result = RunAsConsole
+            elseif (start_mode = "single") then
+                '# start ServiceController.Console()
+                result = RunAsService
             else
                 '# ok, the first paramenter in the commandline didn't work,
                 '# report back so we could send the banner!
                 result = RunAsUnknown
             end if
-        end if
+        '#end if
         
         _dprint("ServiceController.RunMode() done")
         return result
@@ -146,6 +155,8 @@
         dim service as ServiceProcess ptr
         dim commandline as string
         dim success as integer
+        dim logfile as string
+        dim argskip as integer
         
         _dprint("ServiceController.Console()")
         
@@ -154,7 +165,7 @@
         
         '# determine how many service exist in references
         if (_svc_references_count > 0) then
-            _build_commandline(run_mode, service_name, commandline)
+            _build_commandline(run_mode, service_name, commandline,
logfile, argskip)
             service = _find_in_references(service_name)
             
             if (service = 0) then
diff -r -u old/lib/ServiceFB/_internals.bi new/lib/ServiceFB/_internals.bi
--- old/lib/ServiceFB/_internals.bi    2007-06-01 22:22:00.000000000 -0700
+++ new/lib/ServiceFB/_internals.bi    2009-09-10 11:39:12.000000000 -0700
@@ -34,7 +34,7 @@
     '# mode (if present)
     '# valid service name (after lookup in the table)
     '# command line to be passed to service
-    declare sub _build_commandline(byref as string, byref as string, byref
as string)
+    declare sub _build_commandline(byref as string, byref as string, byref
as string, byref as string, byref as integer)
     
     '# I started this as simple, unique service served from one process
     '# but the idea of share the same process space (and reduce resources
use) was good.
diff -r -u old/lib/mongrel_service/init.rb new/lib/mongrel_service/init.rb
--- old/lib/mongrel_service/init.rb    2008-04-17 23:20:00.000000000 -0700
+++ new/lib/mongrel_service/init.rb    2009-09-10 11:39:12.000000000 -0700
@@ -112,6 +112,9 @@
         :debug => @debug, :includes => ["mongrel"], :config_script =>
@config_script,
         :num_procs => @num_procs, :timeout => @timeout, :cpu => @cpu,
:prefix => @prefix
       }
+      
+      
+      argv << "-l \"#{@options[:log_file]}\"" if @options[:log_file]
       
       # if we are using a config file, pass -c and -C to the service
instead of each start parameter.
       if @config_file
@@ -130,7 +133,6 @@
         argv << "-e #{@options[:environment]}" if @options[:environment]
         argv << "-p #{@options[:port]}"
         argv << "-a #{@options[:host]}"  if @options[:host]
-        argv << "-l \"#{@options[:log_file]}\"" if @options[:log_file]
         argv << "-P \"#{@options[:pid_file]}\""
         argv << "-c \"#{@options[:cwd]}\"" if @options[:cwd]
         argv << "-t #{@options[:timeout]}" if @options[:timeout]
diff -r -u old/native/mongrel_service.bas new/native/mongrel_service.bas
--- old/native/mongrel_service.bas    2007-09-24 05:57:00.000000000 -0700
+++ new/native/mongrel_service.bas    2009-09-10 11:39:13.000000000 -0700
@@ -6,7 +6,7 @@
 '# Copyright (c) 2006 Multimedia systems
 '# (c) and code by Luis Lavena
 '# 
-'#  mongrel_service (native) and mongrel_service gem_pluing are licensed
+'#  mongrel_service (native) and mongrel_service gem_plugin are licensed
 '#  in the same terms as mongrel, please review the mongrel license at
 '#  http://mongrel.rubyforge.org/license.html
 '#  
@@ -23,8 +23,17 @@
 #include once "_debug.bi"
 
 namespace mongrel_service
+    
     constructor SingleMongrel()
-        dim redirect_file as string
+        dim redirect_file as string = EXEPATH + "\mongrel.test.log"
+        dim flag as string
+        
+        if(len(command) > 2) then
+            flag = command(2)
+            if(flag = "-l") or (flag = "--log") then
+                redirect_file = command(3)
+            end if
+        end if
         
         with this.__service
             .name = "single"
@@ -40,7 +49,6 @@
         end with
         
         with this.__console
-            redirect_file = EXEPATH + "\mongrel.log"
             debug("redirecting to: " + redirect_file)
             .redirect(ProcessStdBoth, redirect_file)
         end with
@@ -68,6 +76,7 @@
         
         '# due lack of inheritance, we use single_mongrel_ref as pointer to
         '# SingleMongrel instance. now we should call StillAlive
+        
         self.StillAlive()
         if (len(self.commandline) > 0) then
             '# assign the program
@@ -149,11 +158,13 @@
     end sub
     
     sub application()
+            
         dim simple as SingleMongrel
         dim host as ServiceHost
         dim ctrl as ServiceController = ServiceController("Mongrel Win32
Service", "version " + VERSION, _
                                                             "(c) 2006 The
Mongrel development team.")
         
+        
         '# add SingleMongrel (service)
         host.Add(simple.__service)
         select case ctrl.RunMode()
diff -r -u old/native/mongrel_service.bi new/native/mongrel_service.bi
--- old/native/mongrel_service.bi    2007-09-24 05:57:00.000000000 -0700
+++ new/native/mongrel_service.bi    2009-09-10 11:39:13.000000000 -0700
@@ -43,6 +43,7 @@
     
     '# SingleMongrel
     type SingleMongrel
+    
         declare constructor()
         declare destructor()
         
@@ -54,6 +55,7 @@
         __service       as ServiceProcess
         __console       as ConsoleProcess
         __child_pid     as uinteger
+        __log_file        as string
     end type
     
     '# TODO: replace with inheritance here



More information about the Mongrel-users mailing list