Gitart
10/29/2016 - 3:34 PM

App worker

App worker

package main

/*
Run and it will create appmaster.exe which will create a new appworker.exe if it is shutdown.
Must delete appmaster.exe before each run.
Only tested on Windows.
Should build with: -ldflags -H windowsgui
*/

import (
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

const (
	sleepTimeout = 200
)

func main() {
	self := os.Args[0]
	pid := os.Getpid()

	// Start Worker
	if len(os.Args) != 2 {
		slave := strings.Replace(self, "appworker.exe", "appmaster.exe", -1)
		if !fileExists(slave) {
			copyFile(self, slave)

			cmd := exec.Command(slave, string(pid))
			err := cmd.Start()
			if err != nil {
				log.Println("Start error:", err)
			}
			cmd.Process.Release()
		} else {
			for {
				// This is where you do work
				time.Sleep(sleepTimeout * time.Millisecond)
			}
		}
		log.Println("Master:", pid)

	} else { // Start Master
		app := strings.Replace(self, "appmaster.exe", "appworker.exe", -1)
		i, _ := strconv.Atoi(os.Args[1])

		var p *os.Process
		var err error

		// Loop foreach
		for {
			// If process was killed
			if p, err = os.FindProcess(i); err != nil {
				cmd := exec.Command(app)
				err = cmd.Start()
				if err != nil {
					log.Println("Start error:", err)
					break
				}

				i = cmd.Process.Pid
				cmd.Process.Release()

			} else { // Process is still alive
				p.Release()
			}

			time.Sleep(sleepTimeout * time.Millisecond)
		}
	}
}

func copyFile(src string, dst string) {
	// Read all content of src to data
	data, err := ioutil.ReadFile(src)
	if err != nil {
		log.Fatal(err)
	}
	// Write data to dst
	err = ioutil.WriteFile(dst, data, 0644)
	if err != nil {
		log.Fatal(err)
	}
}

func fileExists(filename string) bool {
	if _, err := os.Stat(filename); err == nil {
		return true
	}

	return false
}