func checkAndSpawnDaemon(dfgetLockPath, daemonSockPath string) (client.DaemonClient, error) {
	target := dfnet.NetAddr{Type: dfnet.UNIX, Addr: daemonSockPath}
	daemonClient, err := client.GetClientByAddr([]dfnet.NetAddr{target})
	if err != nil {
		return nil, err
	}

	// 1.Check without lock
	if daemonClient.CheckHealth(context.Background(), target) == nil {
		return daemonClient, nil
	}

	lock := flock.New(dfgetLockPath)
	if err := lock.Lock(); err != nil {
		logger.Errorf("flock lock failed %s", err)
		return nil, err
	}

	defer func() {
		if err := lock.Unlock(); err != nil {
			logger.Errorf("flock unlock failed %s", err)
		}
	}()

	// 2.Check with lock
	if daemonClient.CheckHealth(context.Background(), target) == nil {
		return daemonClient, nil
	}

	cmd := exec.Command(os.Args[0], "daemon", "--launcher", strconv.Itoa(os.Getpid()))
	cmd.Stdin = nil
	cmd.Stdout = nil
	cmd.Stderr = nil
	cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}

	logger.Info("do start daemon")

	err = cmd.Start()
	if err != nil {
		return nil, err
	}

	// 3. check health with at least 5s timeout
	tick := time.NewTicker(50 * time.Millisecond)
	defer tick.Stop()
	timeout := time.After(5 * time.Second)

	for {
		select {
		case <-timeout:
			return nil, errors.New("the daemon is unhealthy")
		case <-tick.C:
			if err = daemonClient.CheckHealth(context.Background(), target); err != nil {
				continue
			}
			return daemonClient, nil
		}
	}
}
// checkAndSpawnDaemon do checking at three checkpoints
checkAndSpawnDaemon do checking at three checkpoints
// checkAndSpawnDaemon do checking at three checkpoints
func checkAndSpawnDaemon(dfgetLockPath, daemonSockPath string) (client.DaemonClient, error) {
	target := dfnet.NetAddr{Type: dfnet.UNIX, Addr: daemonSockPath}
	daemonClient, err := client.GetClientByAddr([]dfnet.NetAddr{target})
	if err != nil {
		return nil, err
	}
	if daemonClient.CheckHealth(context.Background(), target) == nil {
		return daemonClient, nil
	}
	lock := flock.New(dfgetLockPath)
	if err := lock.Lock(); err != nil {
		logger.Errorf("flock lock failed %s", err)
		return nil, err
	}
	defer func() {
		if err := lock.Unlock(); err != nil {
			logger.Errorf("flock unlock failed %s", err)
		}
	}()
	if daemonClient.CheckHealth(context.Background(), target) == nil {
		return daemonClient, nil
	}
	cmd := exec.Command(os.Args[0], "daemon", "--launcher", strconv.Itoa(os.Getpid()))
	cmd.Stdin = nil
	cmd.Stdout = nil
	cmd.Stderr = nil
	cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
	logger.Info("do start daemon")
	err = cmd.Start()
	if err != nil {
		return nil, err
	}
	tick := time.NewTicker(50 * time.Millisecond)
	defer tick.Stop()
	timeout := time.After(5 * time.Second)
	for {
		select {
		case <-timeout:
			return nil, errors.New("the daemon is unhealthy")
		case <-tick.C:
			if err = daemonClient.CheckHealth(context.Background(), target); err != nil {
				continue
			}
			return daemonClient, nil
		}
	}
}
func checkAndSpawnDaemon ( dfgetLockPath , daemonSockPath string ) ( client . DaemonClient , error ) { target := dfnet . NetAddr { Type : dfnet . UNIX , Addr : daemonSockPath } daemonClient , err := client . GetClientByAddr ( [ ] dfnet . NetAddr { target } ) if err != nil { return nil , err } if daemonClient . CheckHealth ( context . Background ( ) , target ) == nil { return daemonClient , nil } lock := flock . New ( dfgetLockPath ) if err := lock . Lock ( ) ; err != nil { logger . Errorf ( " " , err ) return nil , err } defer func ( ) { if err := lock . Unlock ( ) ; err != nil { logger . Errorf ( " " , err ) } } ( ) if daemonClient . CheckHealth ( context . Background ( ) , target ) == nil { return daemonClient , nil } cmd := exec . Command ( os . Args [ 0 ] , " " , " " , strconv . Itoa ( os . Getpid ( ) ) ) cmd . Stdin = nil cmd . Stdout = nil cmd . Stderr = nil cmd . SysProcAttr = & syscall . SysProcAttr { Setsid : true } logger . Info ( " " ) err = cmd . Start ( ) if err != nil { return nil , err } tick := time . NewTicker ( 50 * time . Millisecond ) defer tick . Stop ( ) timeout := time . After ( 5 * time . Second ) for { select { case <- timeout : return nil , errors . New ( " " ) case <- tick . C : if err = daemonClient . CheckHealth ( context . Background ( ) , target ) ; err != nil { continue } return daemonClient , nil } } }
checkAndSpawnDaemon do checking at three checkpoints
checkAndSpawnDaemon do checking at three checkpoints
// 1.Check without lock // 2.Check with lock // 3. check health with at least 5s timeout