// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package impl

// TODO -- Ideally the code in this file would be integrated with the instance reaping,
// so we avoid having two process polling loops. This code is currently separate because
// the actions taken when the app dies (or is caught lying about its pid) prior to being
// considered running are fairly different from what's currently done by the reaper in
// handling deaths that occur after the app started successfully.

import (
	"encoding/binary"
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"

	"v.io/v23/context"
	"v.io/v23/verror"
	vexec "v.io/x/ref/lib/exec"
	"v.io/x/ref/services/device/internal/errors"
	"v.io/x/ref/services/device/internal/suid"
)

// appWatcher watches the pid of a running app until either the pid exits or stop()
// is called
type appWatcher struct {
	pid      int           // Pid to watch
	callback func()        // Called if the pid exits or if stop() is invoked
	stopper  chan struct{} // Used to stop the appWatcher
}

func newAppWatcher(pidToWatch int, callOnPidExit func()) *appWatcher {
	return &appWatcher{
		pid:      pidToWatch,
		callback: callOnPidExit,
		stopper:  make(chan struct{}, 1),
	}
}

func (a *appWatcher) stop() {
	close(a.stopper)
}

func (a *appWatcher) watchAppPid(ctx *context.T) {
	defer a.callback()

	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			if err := syscall.Kill(a.pid, 0); err != nil && err != syscall.EPERM {
				ctx.Errorf("App died in startup: pid=%d: %v", a.pid, err)
				return
			} else {
				ctx.VI(2).Infof("App pid %d is alive", a.pid)
			}

		case <-a.stopper:
			ctx.Errorf("AppWatcher was stopped")
			return
		}
	}
	// Not reached.
}

// appHandshaker is a utility to do the app handshake for a newly started app while
// reacting quickly if the app crashes. appHandshaker reads two pids from the app (one
// from the helper that forked the app, and the other from the app itself). If the app
// appears to be lying about its own pid, it will kill the app.
type appHandshaker struct {
	helperRead, helperWrite *os.File
}

func (a *appHandshaker) cleanup() {
	if a.helperRead != nil {
		a.helperRead.Close()
		a.helperRead = nil
	}
	if a.helperWrite != nil {
		a.helperWrite.Close()
		a.helperWrite = nil
	}
}

// prepareToStart sets up the pipe used to talk to the helper. It must be called before
// the app is started so that the app will inherit the file descriptor
func (a *appHandshaker) prepareToStart(ctx *context.T, cmd *exec.Cmd) error {
	if suid.PipeToParentFD != (len(cmd.ExtraFiles) + vexec.FileOffset) {
		return verror.New(errors.ErrOperationFailed, ctx,
			fmt.Sprintf("FD expected by helper (%v) was not available (%v) (%v)",
				suid.PipeToParentFD, len(cmd.ExtraFiles), vexec.FileOffset))
	}
	var err error
	a.helperRead, a.helperWrite, err = os.Pipe()
	if err != nil {
		ctx.Errorf("Failed to create pipe: %v", err)
		return err
	}
	cmd.ExtraFiles = append(cmd.ExtraFiles, a.helperWrite)
	return nil
}

// doAppHandshake executes the startup handshake for the app. Upon success, it returns the
// pid and appCycle manager name for the started app.
//
// handle should have been set up to use a helper for the app and handle.Start()
// and handle.Wait() should already have been called (so we know the helper is done)
func (a *appHandshaker) doHandshake(ctx *context.T, handle *vexec.ParentHandle, listener callbackListener) (int, string, error) {
	// Close our copy of helperWrite to make helperRead return EOF once the
	// helper's copy of helperWrite is closed.
	a.helperWrite.Close()
	a.helperWrite = nil

	// Get the app pid from the helper. This won't block as the helper is done
	var pid32 int32
	if err := binary.Read(a.helperRead, binary.LittleEndian, &pid32); err != nil {
		ctx.Errorf("Error reading app pid from child: %v", err)
		return 0, "", verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("failed to read pid from helper: %v", err))
	}
	pidFromHelper := int(pid32)
	ctx.VI(1).Infof("read app pid %v from child", pidFromHelper)

	// Watch the app pid in case it exits.
	pidExitedChan := make(chan struct{}, 1)
	watcher := newAppWatcher(pidFromHelper, func() {
		listener.stop()
		close(pidExitedChan)
	})
	go watcher.watchAppPid(ctx)
	defer watcher.stop()

	// Wait for the child to say it's ready and provide its own pid via the init handshake
	childReadyErrChan := make(chan error, 1)
	go func() {
		if err := handle.WaitForReady(childReadyTimeout); err != nil {
			childReadyErrChan <- verror.New(errors.ErrOperationFailed, ctx, fmt.Sprintf("WaitForReady(%v) failed: %v", childReadyTimeout, err))
		}
		childReadyErrChan <- nil
	}()

	// Wait until we get the pid from the app, but return early if
	// the watcher notices that the app failed
	pidFromChild := 0

	select {
	case <-pidExitedChan:
		return 0, "", verror.New(errors.ErrOperationFailed, ctx,
			fmt.Sprintf("App exited (pid %d)", pidFromHelper))

	case err := <-childReadyErrChan:
		if err != nil {
			return 0, "", err
		}
		// Note: handle.Pid() is the pid of the helper, rather than that
		// of the app that the helper then forked. ChildPid is the pid
		// received via the app startup handshake
		pidFromChild = handle.ChildPid()
	}

	if pidFromHelper != pidFromChild {
		// Something nasty is going on (the child may be lying).
		suidHelper.terminatePid(ctx, pidFromHelper, nil, nil)
		return 0, "", verror.New(errors.ErrOperationFailed, ctx,
			fmt.Sprintf("Child pids do not match! (%d != %d)", pidFromHelper, pidFromChild))
	}

	// The appWatcher will stop the listener if the pid dies while waiting below
	childName, err := listener.waitForValue(childReadyTimeout)
	if err != nil {
		suidHelper.terminatePid(ctx, pidFromHelper, nil, nil)
		return 0, "", verror.New(errors.ErrOperationFailed, ctx,
			fmt.Sprintf("Waiting for child name: %v", err))
	}

	return pidFromHelper, childName, nil
}
