netbird icon indicating copy to clipboard operation
netbird copied to clipboard

On Windows, netbird-ui.exe should only run one application instance

Open rgl opened this issue 1 year ago • 3 comments

Describe the problem On Windows, netbird-ui.exe should only run one application instance.

To Reproduce Steps to reproduce the behavior:

  1. Execute netbird-ui.exe.
  2. Execute netbird-ui.exe again.
  3. Notice that two Netbird icons appear in the Windows systray.

Expected behavior It should only show a single icon in the Windows systray.

Screenshots image

rgl avatar Sep 06 '23 19:09 rgl

You ran the regular upgrade with the installer?

mlsmaycon avatar Sep 06 '23 19:09 mlsmaycon

@mlsmaycon, I've used netbird_installer_0.23.0_windows_amd64.exe /S (you can see the full script that installs it at https://github.com/rgl/my-windows-ansible-playbooks/blob/main/roles/netbird/files/install-netbird.ps1).

rgl avatar Sep 07 '23 05:09 rgl

I ran into this issue as well on windows 10. After adding in some debug logging when it got to process.Signal(syscall.Signal(0)) it output signal: not supported by windows.

Looking at this post https://stackoverflow.com/questions/15204162/check-if-a-process-exists-in-go-way I was able to make the process not start multiple instances on windows by modifying checkPIDFile to the following. There are likely better methods of doing this, but it is outside of my skill-set to properly implement.

I also tested on ubuntu 20.04 by backgrounding the process and attempting to start it several times, which resulted in it correctly not starting another instance of the executable instead returning the error from the section where syscall is executed.

This might be one way to go about it minimal change, just going to leave this here as food for thought.

// checkPIDFile exists and return error, or write new.
func checkPIDFile() error {
	pidFile := path.Join(os.TempDir(), "wiretrustee-ui.pid")
	if piddata, err := os.ReadFile(pidFile); err == nil {
		if pid, err := strconv.Atoi(string(piddata)); err == nil {
			if process, err := os.FindProcess(pid); err == nil {
				if runtime.GOOS == "windows" {
					return fmt.Errorf("process already exists: %d", pid)
				} else if err := process.Signal(syscall.Signal(0)); err == nil {
					return fmt.Errorf("process already exists: %d", pid)
				}
			}
		}
	}

	return os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", os.Getpid())), 0o664) //nolint:gosec
}

mfuller-vso avatar Jan 23 '24 23:01 mfuller-vso