0

Please note, the Django server is Daphne, but the websockify command has nothing to do with Daphne channels.

I have the following oversimplified code in Django view:

def openvnc_connection(request):
    Popen(['websockify'. "--run-once", "--daemon", "--timeout", "30", "--idle-timeout", "60", "--cert", ...])
    ...

Problem is when I deploy the code, involves restarting the Daphne worker service, the websockify process gets killed as well, resulting any active vnc connection gets dropped.

I am aware the websockify process is the child of the django process and it gets killed because of that.

I have tried the double-fork or similar stuff like detaching the child process but they don't seem to work and websockify process still gets killed when restarting Daphne worker.

Tried double fork:

def spawnDaemon(port, target):
    import os, sys, subprocess
    # do the UNIX double-fork magic, see Stevens' "Advanced
    # Programming in the UNIX Environment" for details (ISBN 0201563177)
    try:
        pid = os.fork()
        if pid > 0:
            # parent process, return and keep running
            return
    except Exception as e:
        print(sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror))
        sys.exit(1)

    os.setsid()

    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except Exception as e:
        print(sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror))
        sys.exit(1)

    # do stuff
    Popen(['websockify'. "--run-once", "--daemon", "--timeout", "30", "--idle-timeout", "60", "--cert", ...])

    # all done
    os._exit(os.EX_OK)
James Lin
  • 25,028
  • 36
  • 133
  • 233

1 Answers1

0

So... I went for a huge detour, tried to spawn the websockify through another python code which does the double fork:

def double_fork():
    try:
        pid = os.fork()
        if pid > 0:
            # parent process, return and keep running
            return
    except Exception as e:
        sys.exit(1)

    os.setsid()

    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except Exception as e:
        logger.error("fork #2 failed: %d (%s)" % (e.errno, e.strerror))
        sys.exit(1)

    from websockify.websocketproxy import WebSocketProxy, LibProxyServer
    WebSocketProxy(run_once=True, timeout=30, idle_timeout=60, target_host=sys.argv[1], target_port=sys.argv[2], listen_port=sys.argv[3],
            cert=cert, key=key, daemon=False).start_server()

Which led to able to double forked fine but still getting killed when I run sudo systemctl restart ..., then further searching found this answer, and it worked for me, just need to add to the service block.

KillMode=process

Then I also tried without the new python script to double fork, by just calling the old Popen(...), I believe it also spawns a daemon process, and it's also working.

James Lin
  • 25,028
  • 36
  • 133
  • 233