Search code examples
windowsservicecygwinregistryposix

Running Cygwin application as a Windows Service


I am working on WinDRBD (https://github.com/LINBIT/windrbd) a port of the Linux DRBD driver to Microsoft Windows.

We want to run the user mode helper as a Windows Service (DRBD sometimes calls user space applications with call_usermodehelper(), which we emulate by a daemon that retrieves those request from the kernel driver, runs them and returns the exit status to the kernel).

When we run the daemon in a cygwin shell, everything works fine. However when running the daemon as a Windows Service it seems that cygwin cannot find its installation directory (which is C:\cygwin64 on my machines).

The registry entry (HKLM/Software/CygWin/setup/rootdir) points to the correct location, but I am not sure if it can also be accessed by the Windows Service?

/bin/sh isn't found by the service, however /cygdrive/c/cygwin64/bin/sh exists, so when I run the shell with that path it can start (and also finds the DLLs it requires to run). However shell complains with:

bash.exe: warning: could not find /tmp, please create!

which definitely exists when running cygwin the normal way.

Has anyone ever tried to run a CygWin compiled EXE as a Windows Service? Here is the output of sc query windrbdum:

SERVICE_NAME: windrbdum 
    TYPE               : 10  WIN32_OWN_PROCESS  
    STATE              : 4  RUNNING 
                            (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
    WIN32_EXIT_CODE    : 0  (0x0)
    SERVICE_EXIT_CODE  : 0  (0x0)
    CHECKPOINT         : 0x0
    WAIT_HINT          : 0x0

(um is for user mode).

Thanks for any insights,

  • Johannes

Solution

  • As matzeri pointed out, cygrunsrv is the cygwin tool when it comes to running cygwin binaries as a service under Windows. It serves both as a wrapper (that does the Windows specific service API and event handling) as well as a tool to install, remove, start and stop services (this can still be done with the sc utility like

    sc start <servicename>
    

    ).

    To install a service (I) do:

    cygrunsrv.exe -I windrbdlog -p /cygdrive/c/windrbd/usr/sbin/windrbd.exe \
      -a log-server \ 
      -1 /cygdrive/c/windrbd/windrbd-kernel.log \ 
      -2 /cygdrive/c/windrbd/windrbd-kernel.log
    

    where windrbdlog is the Windows name of the service, /cygdrive ... is the full path to the cygwin application (no need to code any Windows Service API calls there, it's just a Cygwin/POSIX executable), log-server is the argument to the binary (so what is being started is windrbd log-server) and -1 and -2 are rediects for stdout and stderr. Exactly what I need, thanks to matzeri for pointing me to cygrunsrv.