[Twisted-Python] Daemon processes on windows

Brian Granger ellisonbg.net at gmail.com
Sun Nov 8 00:22:15 EST 2009


Fantastic, thanks for sharing this code.  I will definitely have a look.  If
it turns out to
work for us, would you mind releasing this under a BSD license so we can
include
it in IPython (BSD open source project)?  In either case, the ideas will be
very helpful to us.

Cheers,

Brian

It is possible to daemonize a process on Windows. I experimented with
> adding that support to the twistd script, but got swamped with other
> work and couldn't finish it. Below is the code that I have so far. You
> can save it in a module and call the daemonize() function from your script.
>
> The process of daemonization is similar to the one on UNIX -- you have
> to spawn a child process twice, the first child is responsible for
> breaking away from any job objects (somewhat similar to becoming a
> session leader on UNIX), becoming a new process group leader and closing
> all handles (file descriptors) that might have been inherited.
>
> The second child has to open dummy std* files and a new (hidden)
> console, otherwise the signals stop working. There is a slight
> complication with window stations and desktops. Each console creates at
> least one window and some other user objects, so we have to create
> a separate desktop, or other processes would be able to manipulate them
>  and send us arbitrary (Windows) messages.
>
> Regards,
> Ziga
>
>
>
> import os
> import sys
> import msvcrt
>
> import win32con
> import win32process
> import win32security
> import win32service
>
> from twisted.python import win32
>
>
>
> def getPythonArgs():
>     """
>     Return the list of command line args that were used to start
>     the current Python interpreter and were not stored in C{sys.argv}.
>
>     These are the options that control the Python interpreter itself,
>     like the Python executable, optimization level, warning filters,
>     division behaviour and literal string handling.
>     """
>     args = [sys.executable]
>     for warnoption in sys.warnoptions:
>         args.append("-W")
>         args.append(warnoption)
>     if type(1 / 2) is not int:
>         args.append("-Qnew")
>     if type("") is not str:
>         args.append("-U")
>     if not __debug__:
>         if getPythonArgs.__doc__ is None:
>             args.append("-OO")
>         else:
>             args.append("-O")
>     return args
>
>
>
> def daemonize():
>     args = [os.path.abspath(__file__)] + sys.argv
>     executable = sys.executable
>     cmdline = win32.quoteArguments(getPythonArgs() + args)
>     inherit = False
>
>     flags = (win32process.CREATE_BREAKAWAY_FROM_JOB | # session leader
>              win32process.CREATE_NEW_PROCESS_GROUP |  # group leader
>              win32process.DETACHED_PROCESS) # no controlling terminal
>
>     info = win32process.STARTUPINFO()
>     win32process.CreateProcess(executable, cmdline, None, None,
>                                inherit, flags, None, None, info)
>     # Do what exec* functions do, let the OS do the cleanup.
>     os._exit(0)
>
>
>
> def daemonize2():
>     args = [sys.argv[1], "--nodaemon"] + sys.argv[2:]
>     executable = sys.executable
>     cmdline = win32.quoteArguments(getPythonArgs() + args)
>     inherit = True
>     # create an invisible console
>     flags = (win32process.CREATE_NO_WINDOW
>     attributes = win32security.SECURITY_ATTRIBUTES()
>     attributes.bInheritHandle = True
>     station = win32service.CreateWindowStation(None, 0,
>                                                win32con.GENERIC_READ |
>                                                win32con.GENERIC_WRITE,
>                                                attributes)
>     station.SetProcessWindowStation()
>     sname = win32service.GetUserObjectInformation(station,
>                                                   win32service.UOI_NAME)
>     dname = str(os.getpid())
>     desktop = win32service.CreateDesktop(dname, 0,
>                                          win32con.GENERIC_READ |
>                                          win32con.GENERIC_WRITE,
>                                          attributes)
>     desktop.SetThreadDesktop()
>     null = os.open("NUL", os.O_RDWR)
>     handle = msvcrt.get_osfhandle(null)
>     info = win32process.STARTUPINFO()
>     info.lpDesktop = "%s\\%s" % (sname, dname)
>     info.dwFlags = win32process.STARTF_USESTDHANDLES
>     info.hStdInput = info.hStdOutput = info.hStdError = handle
>     win32process.CreateProcess(executable, cmdline, None, None,
>                                inherit, flags, None, None, info)
>     # Same as above, exit as fast as possible.
>     os._exit(0)
>
>
>
> if __name__ == "__main__":
>     daemonize2()
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20091107/a17e106f/attachment-0001.htm 


More information about the Twisted-Python mailing list