Hey,

Thanks for your response Dan! More examples are always needed. However, i think 
there is a miscommunication. That sample code you wrote is using the pywin32 
code to write a windows service. This isn't what I was using, but I might have 
to use that if i can't get the other method (i'll explain below) to work. Were 
you able to get that script to compile as a cx_freeze exe? Whatever method I 
use, i need to have it be frozen as an EXE as python is not guaranteed  to be 
installed on the computers that this service will be running on, and all the 
examples i've seen that use pywin32 seem to be assuming that python is 
installed.

***TLDR AT END OF MESSAGE****

ANYWAY, the method I WAS using is actually built into cx_freeze. You would 
never know its there, because its basically hidden in the source code, and even 
if you compile it yourself, you need another dependency that it never mentions 
(unless you look into the source code) or else it won't compile it (you need 
Cx_logging, and it needs to be in the parent folder of cx_freeze or else it 
won't find it, very annoying to figure out !).

You can see the 'example' code for the win32 service in the cx_freeze repo: 
https://bitbucket.org/anthony_tuininga/cx_freeze/src/1282b6b6ee63/cx_Freeze/samples/service/?at=default
 
<https://bitbucket.org/anthony_tuininga/cx_freeze/src/1282b6b6ee63/cx_Freeze/samples/service/?at=default>

and the win32service.c base that cx_freeze uses (basically a windows program 
that embeds python, and registers a "Session Changed" function, that basically 
calls 1 of 3 python functions, Initialize(), Run(), and Stop() in your python 
code:
https://bitbucket.org/anthony_tuininga/cx_freeze/src/1282b6b6ee637738210113dd88c3c198d475340f/source/bases/Win32Service.c?at=default
 
<https://bitbucket.org/anthony_tuininga/cx_freeze/src/1282b6b6ee637738210113dd88c3c198d475340f/source/bases/Win32Service.c?at=default>

I honestly like the cx_freeze method better, as its simpler, and this windows 
service is so stupidly simple that I didn't want to take the time to figure out 
the pywin32 method. All my service needs to do is to start a python process, 
and then when the service stops (windows shuts down, logs off), it sends a 
CTRL_BREAK signal to the child python process to signal that it needs to exit 
gracefully.

The code I've written so far is posted here, you need cx_freeze with cx_logging 
and the win32service.c file compiled with the cx_freeze build: (using python 3 
/ asyncio)

https://gist.github.com/mgrandi/aa70c902fa7e2215a228 
<https://gist.github.com/mgrandi/aa70c902fa7e2215a228>

It looks complicated, mainly because i'm using asyncio, and the python code in 
service.py gets called from multiple threads, but the general explanation:

* Initialize() is called
* Run() is called, tells the asyncio event loop to run 'do_loop()' until it 
finishes.
---- do_loop() runs, which creates a new process, as a NEW PROCESS GROUP 
(IMPORTANT), then waits on it to exit.
* <time passes>
* Someone hits "stop" in the windows service manager, or the computer is 
shutting down, whatever, the windows service stuff tells the service to stop, 
which in turn calls Stop() in python code, which is on a different thread then 
what Run() is currently running on
----Stop() tells the event loop (that is running on the main python thread, 
asyncio event loops are specific to the thread they are started on), to call 
'stop_loop()' soon on its thread, and then Stop() returns
-------- stop_loop() runs, is running on the same thread as Run() and 
do_loop(), sends the CTRL_BREAK signal to the process that do_loop() is waiting 
for to exit. The child process _should_ exit, and then stop_loop() then waits 
on an event.
-------- run_loop() then sees the process exits, and then 'sets' the event, and 
then returns. Then stop_loop() sees that the event is now set, and then it 
tells the event loop to stop.
-------- back in Run(), now that the loop is stopped, loop.run_until_complete() 
(or run_forever(), tried both combinations) now stops blocking and Run() 
finishes, and returns.
* now that Run() has exited, i'm assuming the cx_freeze win32service.c wrapper 
tells the windows service stuff that the process is now stopped, and then the 
actual service EXE exits


Now that you have read all that (haha), if you see in service.py, i have a 
dummy class TestThread, which i use to 'test' this, as you mentioned yourself 
that its almost impossible to really debug windows services as its an EXE, but 
its treated like a DLL almost. To test it in just python, i just uncomment 
lines 51-52 in service.py, and then just run in the python interactive shell 
"import service; x=service.Handle(); x.Initialize("something"); x.Run()", and 
then the same code runs, and then the thread will manually call the Stop() 
method after 20 seconds.

*****TLDR HERE*****
The log of this running (in the interactive shell) is here: (service.py log is 
the actual windows service, catcher_async.py is the 'childprocess' that is 
waiting for CTRL_BREAK).

https://gist.github.com/mgrandi/9a168e1ef537e8052a33 
<https://gist.github.com/mgrandi/9a168e1ef537e8052a33>

Yes i know the logs don't match up exactly, i have a lot of them, but even 
though the times/pids don't match its the same output)

but when i run it as a cx_freeze frozen windows service, and i register it, 
start it, wait a few seconds then stop it, i get this:

 https://gist.github.com/mgrandi/b064d99ddb28c73d398c 
<https://gist.github.com/mgrandi/b064d99ddb28c73d398c>

Note that in the service.py log, there is the line "root|send_signal|13996: HEY 
GIRL ABOUT TO SEND SIGNAL DAWG", that is a logging statement i put in 
subprocess.py (the python module subprocess), to further debug where its 
failing, because as you can see in the service.py log, i'm getting a completely 
bogus python stack trace. If I comment out the line it says threw the exception 
(logging.info("SENT THE SIGNAL DAWG"), a statement i put in subprocess.py after 
the os.kill() call, again debugging stuff), then it will say some other random 
line caused the WinError, and again and again.

Obviously something is going wrong with calling os.kill() when this script is 
running in the cx_freeze win32service.c wrapper, but i have no idea what as the 
stack trace is bogus, and its probably a problem in the C code anyway so a 
python stack trace wouldn't help anyway. "[WinError 6] The handle is invalid" 
is basically a python wrapped Win32 error code , and since those are vague as 
all heck intentionally, i have no idea which handle it is, or why its invalid, 
etc. If i could get the source to the generated exe that cx_freeze generates 
somehow then i could run it in visual studio and debug it further, but I can't 
figure out how to do that.

So I know this is long, but I've spent way too much time for something that 
should be relatively simple. I'm either going to have to use pywin32 (if i can 
get that to compile as an exe) or just start a detached process and then check 
every X minutes to see if its still running. Any help would be greatly 
appreciated.

~Mark






> On Feb 19, 2015, at 11:39 AM, Dan McCombs <dmcco...@dyn.com> wrote:
> 
> Hi Mark,
> 
> You are absolutely right about the lack of documentation on this, it was a 
> big pain in a project I worked on last year. I should probably put a blog 
> post together somewhere...
> 
> I don't have a lot of time at the moment, but I took a couple of minutes to 
> strip down some of my code to just the basic parts for a Windows service. I 
> haven't actually tried using this stand alone, but it should give you a 
> better idea of what's entailed to get it working and hopefully answer some 
> questions. My biggest issue with getting this working is it was very hard to 
> get any kind of real debugging output in the case where the service just 
> wouldn't start for some reason.
> 
> https://gist.github.com/dmccombs/49f2f0de3c3f9bd452f2 
> <https://gist.github.com/dmccombs/49f2f0de3c3f9bd452f2>
> 
> Hopefully this can help point you in the right direction, and if you have 
> more specific questions after playing with this I'll try to answer them.
> 
> Take care,
> 
> -Dan
> 
>  <http://dyn.com/>         <http://twitter.com/dyn> 
> <http://twitter.com/dyninc>    <http://facebook.com/dyn>    
> <http://linkedin.com/company/dyn>
> Dan McCombs  / Senior Software Engineer
>  603 296 1568      @danmccombs <http://twitter.com/danmccombs/>
> 
> 
> On Wed, Feb 18, 2015 at 11:16 PM, Mark Grandi <markgra...@gmail.com 
> <mailto:markgra...@gmail.com>> wrote:
> I have some questions about using cx_freeze to create a python windows 
> service. Since there is literally 0 documentation about this, I had to look 
> at the source for a lot of things, but I still have some questions. I am 
> running python3 64 bit if it helps.
> 
> 1: What is the lifecycle of the windows service? Obviously the first things 
> that get called are Initialize() and Run(), but what happens after that? I 
> know Run() keeps going, but mainly, what should be the last method to return? 
> Should Run() exit before Stop()? Its unclear from Win32Service.c what is 
> supposed to exit first.
> 
> 2: Is there any way to get the 'generated source' for the exe? I'm having 
> problems with my program and it seems to only happen when its compiled as an 
> exe, (getting a WinError: Invalid Handle with a bogus stack trace) so i'm 
> thinking its something in the C part of the exe, but I can't really debug it 
> as I don't have the source to have visual studio step through / set 
> breakpoints. Or should I make a separate message about this problem?
> 
> ~Mark Grandi
> 
> ------------------------------------------------------------------------------
> Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
> from Actuate! Instantly Supercharge Your Business Reports and Dashboards
> with Interactivity, Sharing, Native Excel Exports, App Integration & more
> Get technology previously reserved for billion-dollar corporations, FREE
> http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk 
> <http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk>
> _______________________________________________
> cx-freeze-users mailing list
> cx-freeze-users@lists.sourceforge.net 
> <mailto:cx-freeze-users@lists.sourceforge.net>
> https://lists.sourceforge.net/lists/listinfo/cx-freeze-users 
> <https://lists.sourceforge.net/lists/listinfo/cx-freeze-users>
> 
> 
> ------------------------------------------------------------------------------
> Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
> from Actuate! Instantly Supercharge Your Business Reports and Dashboards
> with Interactivity, Sharing, Native Excel Exports, App Integration & more
> Get technology previously reserved for billion-dollar corporations, FREE
> http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk_______________________________________________
> cx-freeze-users mailing list
> cx-freeze-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/cx-freeze-users

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk
_______________________________________________
cx-freeze-users mailing list
cx-freeze-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cx-freeze-users

Reply via email to