Home > Blockchain >  How to perform socket activation, passing a socket to a child proc as stdin/out, in golang?
How to perform socket activation, passing a socket to a child proc as stdin/out, in golang?

Time:11-10

I have a C program that runs via systemd socket activation. Systemd listens on a port and when a TCP connections comes in, then the application is launched and it treats stdin/stdout exactly like a socket (IE: setsockopt, etc) .

I am trying to mimic this behavior with a small launching program in go. It will just be told what port to listen on and what command to run when a connection is made to it (none of the other advanced systemd features).

The problem I am having is that I don't seem to be able to pass the connection as a socket to stdin/out. Passing the TCPConn to Stdin and Stdout of the Cmd did not work (the C program errored on setsockopts).

            cmd := exec.Cmd{
                Path:   cmds,
                Args:   args,
                Stdin:  conn.,
                Stdout: conn,
                Stderr: os.Stderr,
            }
            err = cmd.Run()

I saw an article on how to do something like this in C using dup(2) and fork, but

  • it is forking not exec-ing another child process
  • I don't entirely understand with the socket fd is being duplicated and not the client accepted connection

Is there any way to do something like this in Golang?

aditional info

the socket file looks roughly like

[Unit]
Description=soc activated program 

[Socket]
ListenStream=0.0.0.0:10101
Accept=yes

[Install]
WantedBy=sockets.target

and corresponding unit file looks like:

[Unit]
Description=My Program 

[Service]
Type=simple
ExecStart=/usr/bin/myprog -N
StandardInput=socket
StandardOutput=socket
StandardError=journal
TimeoutStopSec=5
KillMode=process

[Install]
WantedBy=multi-user.target

CodePudding user response:

Use the connections's file:

        f, err := conn.File()
        if err != nil { /* TODO handle error */}
        defer f.Close()

        cmd := exec.Cmd{
            Path:   cmds,
            Args:   args,
            Stdin:  f,
            Stdout: f,
            Stderr: os.Stderr,
        }
        err = cmd.Run()
  • Related