title: Golang exec process and to disown it
body: <p>I am trying to fork processes with my daemon, and trying to disown them in case of my daemon crashes. Regular <code>os/exec</code> is high-level, therefore I went for <code>syscall.ForkExec</code> and produced the following code:</p>
  
  <pre><code>package main
  
  import (
      "fmt"
      "os"
      "os/exec"
      "syscall"
      "time"
  )
  
  func main() {
  
      cmd := "myproc"
      binary, lookErr := exec.LookPath(cmd)
      if lookErr != nil {
          panic(lookErr)
      }
      fmt.Println(binary)
  
      os.Remove("/tmp/stdin")
      os.Remove("/tmp/stdout")
      os.Remove("/tmp/stderr")
  
      fstdin, err1 := os.Create("/tmp/stdin")
      fstdout, err2 := os.Create("/tmp/stdout")
      fstderr, err3 := os.Create("/tmp/stderr")
      if err1 != nil || err2 != nil || err3 != nil {
          fmt.Println(err1, err2, err3)
          panic("WOW")
      }
  
      argv := []string{"hi"}
      procAttr := syscall.ProcAttr{
          Dir:   "/tmp",
          Files: []uintptr{fstdin.Fd(), fstdout.Fd(), fstderr.Fd()},
          Env:   []string{"VAR1=ABC123"},
          Sys: &amp;syscall.SysProcAttr{
              Foreground: false,
          },
      }
  
      pid, err := syscall.ForkExec(binary, argv, &amp;procAttr)
      fmt.Println("Spawned proc", pid, err)
  
      time.Sleep(time.Second * 100)
  }
  </code></pre>
  
  <p>I have also made a simple application that sleeps and prints hello world and put it to path.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  
  int main(){
      while(1){
          printf("hello world");
          fflush(stdout);
          usleep(300000);
          }
  }
  </code></pre>
  
  <p>It works, however, the process is not send to background as I expected, my go process still owns the child. The <code>SysProcAttr</code> has the following values in Linux:</p>
  
  <pre><code>type SysProcAttr struct {
      Chroot      string         // Chroot.
      Credential  *Credential    // Credential.
      Ptrace      bool           // Enable tracing.
      Setsid      bool           // Create session.
      Setpgid     bool           // Set process group ID to Pgid, or, if Pgid == 0, to new pid.
      Setctty     bool           // Set controlling terminal to fd Ctty (only meaningful if Setsid is set)
      Noctty      bool           // Detach fd 0 from controlling terminal
      Ctty        int            // Controlling TTY fd
      Foreground  bool           // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY)
      Pgid        int            // Child's process group ID if Setpgid.
      Pdeathsig   Signal         // Signal that the process will get when its parent dies (Linux only)
      Cloneflags  uintptr        // Flags for clone calls (Linux only)
      UidMappings []SysProcIDMap // User ID mappings for user namespaces.
      GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
      // GidMappingsEnableSetgroups enabling setgroups syscall.
      // If false, then setgroups syscall will be disabled for the child process.
      // This parameter is no-op if GidMappings == nil. Otherwise for unprivileged
      // users this should be set to false for mappings work.
      GidMappingsEnableSetgroups bool
  }
  </code></pre>
  
  <p>I also tried the following but It caused an error:</p>
  
  <pre><code>Sys: &amp;syscall.SysProcAttr{
      Setsid:     true,
      Setctty:    true,
      Foreground: false,
   },
  
  Spawned proc 0 inappropriate ioctl for device
  </code></pre>
  
  <p>Also the following:</p>
  
  <pre><code>Sys: &amp;syscall.SysProcAttr{
      Setsid:     true,
      Setctty:    true,
      Foreground: false,
      Noctty:     true,
      Setpgid:    true,
  },
  
  Spawned proc 0 operation not permitted (with root privilleges)
  </code></pre>
  
  <p>What am I doing/assuming wrong?
  <strong>Note:</strong> Despite saying os/exec is high-level, I also tried the following, but it produced same results.</p>
  
  <pre><code>cs := exec.Command(binary)
  cs.SysProcAttr = &amp;syscall.SysProcAttr{
      Setctty: true,
  }
  err := cs.Run()
  fmt.Println(err)
  </code></pre>