Daniel Berger
2007-Nov-24 13:09 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Hi, Unless I''m mistaken the final arguments to Service.start should be passed to the Daemon''s service_main method. Correct? I modified the Service.start method (now in CVS) to look something like this: def self.start(service, host=nil, *args) ... num_args = args.length if args.empty? args = nil else args.unshift(service) # Necessary? args = [args.join("\000")].pack(''p*'') # Must pack? end unless StartService(handle_scs, num_args, args) ... end I wasn''t sure if I needed to explicitly push the service name onto the array, but it does segfault without it. I also wasn''t sure if I needed to explicitly pack the array. Again, it segfaulted without it. To test, I modified the demo_daemon.rb file''s service_main method so that it looks like this: def service_main(args = nil) msg = ''service_main entered at: '' + Time.now.to_s File.open(LOG_FILE, ''a+''){ |f| f.puts msg f.puts "Args: " + args.join('','') if args } ... end In the demo_daemon_ctl.rb script, I modified the start option like so: Service.start(SERVICE_NAME, nil, ''hello'', ''world'') As things stand now I get: C:/ruby/lib/ruby/site_ruby/1.8/win32/service.rb:684:in `start'': The service did not respond to the start or control requ est in a timely fashion. (Win32::Service::Error) from demo_daemon_ctl.rb:66 Any ideas? Thanks, Dan
Heesob Park
2007-Nov-24 14:17 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Hi, 2007/11/24, Daniel Berger <djberg96 at gmail.com>:> > Hi, > > Unless I''m mistaken the final arguments to Service.start should be > passed to the Daemon''s service_main method. Correct? > > I modified the Service.start method (now in CVS) to look something like > this: > > def self.start(service, host=nil, *args) > ... > num_args = args.length > > if args.empty? > args = nil > else > args.unshift(service) # Necessary? > args = [args.join("\000")].pack(''p*'') # Must pack? > end > > unless StartService(handle_scs, num_args, args) > ... > end > > I wasn''t sure if I needed to explicitly push the service name onto the > array, but it does segfault without it. > > I also wasn''t sure if I needed to explicitly pack the array. Again, it > segfaulted without it.Don''t ask me why, just follow the rule of the microsoft :) Acording to http://msdn2.microsoft.com/en-US/library/ms686321.aspx , StartService function requires NULL or an argument which the first element must be service name. And argument type is not LPCSTR, but LPCTSTR* ( pointer of string), so it need to be packed. To test, I modified the demo_daemon.rb file''s service_main method so> that it looks like this: > > def service_main(args = nil) > msg = ''service_main entered at: '' + Time.now.to_s > File.open(LOG_FILE, ''a+''){ |f| > f.puts msg > f.puts "Args: " + args.join('','') if args > } > ... > end > > In the demo_daemon_ctl.rb script, I modified the start option like so: > > Service.start(SERVICE_NAME, nil, ''hello'', ''world'') > > As things stand now I get: > > C:/ruby/lib/ruby/site_ruby/1.8/win32/service.rb:684:in `start'': The > service did not respond to the start or control requ > est in a timely fashion. (Win32::Service::Error) > from demo_daemon_ctl.rb:66 > > Any ideas?Regards, Park Heesob -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/win32utils-devel/attachments/20071124/05e4ce86/attachment-0001.html
Daniel Berger
2007-Nov-24 14:29 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Heesob Park wrote: <snip>> I wasn''t sure if I needed to explicitly push the service name onto the > array, but it does segfault without it. > > I also wasn''t sure if I needed to explicitly pack the array. Again, it > segfaulted without it. > > > Don''t ask me why, just follow the rule of the microsoft :) > > Acording to http://msdn2.microsoft.com/en-US/library/ms686321.aspx , > StartService function requires NULL or an argument which the first > element must be service name. > And argument type is not LPCSTR, but LPCTSTR* ( pointer of string), so > it need to be packed.Ok, then what I have should work. I did notice a mistake in the demo_daemon_ctl.rb program (which I fixed in CVS), so now it runs ok, but the args don''t appear to get passed to service_main. Are you seeing the same thing? Regards, Dan
Daniel Berger
2007-Nov-24 14:40 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Heesob Park wrote: <snip>> Don''t ask me why, just follow the rule of the microsoft :) > > Acording to http://msdn2.microsoft.com/en-US/library/ms686321.aspx , > StartService function requires NULL or an argument which the first > element must be service name. > And argument type is not LPCSTR, but LPCTSTR* ( pointer of string), so > it need to be packed.Oops, I did see a mistake with num_args. It should be like this I think: num_args = 0 if args.empty? args = nil else args.unshift(service) num_args = args.length args = [args.join("\000")].pack(''p*'') end I forgot to add 1 for the service name. The only problem is, now it segfaults. :( Dan
Heesob Park
2007-Nov-24 16:05 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Hi, 2007/11/24, Daniel Berger <djberg96 at gmail.com>:> Heesob Park wrote: > > <snip> > > > Don''t ask me why, just follow the rule of the microsoft :) > > > > Acording to http://msdn2.microsoft.com/en-US/library/ms686321.aspx , > > StartService function requires NULL or an argument which the first > > element must be service name. > > And argument type is not LPCSTR, but LPCTSTR* ( pointer of string), so > > it need to be packed. > > Oops, I did see a mistake with num_args. It should be like this I think: > > num_args = 0 > > if args.empty? > args = nil > else > args.unshift(service) > num_args = args.length > args = [args.join("\000")].pack(''p*'') > end > > I forgot to add 1 for the service name. > > The only problem is, now it segfaults. :( > > DanI figured it out finally. First, fix argument type. you don''t need to put the first element as service name as documented. The code service.rb before StartService should be like this: num_args = 0 if args.empty? args = nil else # args.unshift(service) --> this is optional num_args = args.length args = args.map {|x| [x].pack(''p*'')}.join end Second, you did''nt send argument from Service_Main C function to service_main ruby methods. The code daemon.c shoud be like this: Before RegisterServiceCtrlHandler of Service_Main function if(dwArgc>1) { int i; Argc = dwArgc-1; // declared STATIC int Arg; on top Argv = malloc(sizeof(VALUE)*Argc); // declared STATIC VALUE *Argv; on top for(i=1;i<dwArgc;i++) Argv[i-1]=rb_str_new2(lpszArgv[i]); } daemon_mainloop_protect function static VALUE daemon_mainloop_protect(VALUE self) { if(rb_respond_to(self,rb_intern("service_main"))) { if(Argc==0) rb_funcall(self,rb_intern("service_main"),0); else rb_funcall2(self,rb_intern("service_main"),Argc,Argv); } return self; } Regards, Park Heesob -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/win32utils-devel/attachments/20071125/6c35c39a/attachment.html
Daniel Berger
2007-Nov-24 17:53 UTC
[Win32utils-devel] Service.start arguments failing or causing segfault
Heesob Park wrote:> Hi, > > 2007/11/24, Daniel Berger <djberg96 at gmail.com <mailto:djberg96 at gmail.com>>: > > Heesob Park wrote: > > <snip> > > > Don''t ask me why, just follow the rule of the microsoft :) > > > > Acording to http://msdn2.microsoft.com/en-US/library/ms686321.aspx , > > StartService function requires NULL or an argument which the first > > element must be service name. > > And argument type is not LPCSTR, but LPCTSTR* ( pointer of > string), so > > it need to be packed. > > Oops, I did see a mistake with num_args. It should be like this I > think: > > num_args = 0 > > if args.empty? > args = nil > else > args.unshift(service) > num_args = args.length > args = [args.join("\000")].pack(''p*'') > end > > I forgot to add 1 for the service name. > > The only problem is, now it segfaults. :( > > Dan > > > I figured it out finally. > > First, fix argument type. you don''t need to put the first element as > service name as documented. > The code service.rb before StartService should be like this: > > num_args = 0 > if args.empty? > args = nil > else > # args.unshift(service) --> this is optional > num_args = args.length > args = args.map {|x| [x].pack(''p*'')}.join > end > > Second, you did''nt send argument from Service_Main C function to > service_main ruby methods. > The code daemon.c shoud be like this: > > Before RegisterServiceCtrlHandler of Service_Main function > > if(dwArgc>1) { > int i; > Argc = dwArgc-1; // declared STATIC > int Arg; on top > Argv = malloc(sizeof(VALUE)*Argc); // declared STATIC VALUE *Argv; > on top > for(i=1;i<dwArgc;i++) > Argv[i-1]=rb_str_new2(lpszArgv[i]); > } > > daemon_mainloop_protect function > > static VALUE daemon_mainloop_protect(VALUE self) > { > if(rb_respond_to(self,rb_intern("service_main"))) > { > if(Argc==0) > rb_funcall(self,rb_intern("service_main"),0); > else > rb_funcall2(self,rb_intern("service_main"),Argc,Argv); > } > return self; > }Awesome, that works! Thanks! I think that was the last thing I wanted to get worked out for 0.6.0. I''ll get a release out today or tomorrow. Thanks, Dan