arduino-cli icon indicating copy to clipboard operation
arduino-cli copied to clipboard

Recover from interrupted discovery/monitor installation

Open per1234 opened this issue 3 years ago • 4 comments
trafficstars

Describe the request

Reinstall pluggable discovery and monitor tools of the builtin package if the tool executable is not found.

Describe the current behavior

Arduino CLI automatically installs pluggable discovery and pluggable monitor tools of the builtin package when missing or updatable. These tools allow Arduino CLI to find the "ports" used for communication with Arduino boards.

It can happen that the installation is interrupted while in progress.

🙁 If a problem during the installation results in the creation of the tool's release installation folder without the tool executable, Arduino CLI can no longer do discovery. It will not automatically recover from this condition and the user must manually delete the incomplete installation in order to restore Arduino CLI to functionality.

To reproduce

$ ./arduino-cli version
arduino-cli  Version: nightly-20220218 Commit: dd48868 Date: 2022-02-18T01:31:17Z

$ rm ~/.arduino15/packages/builtin/tools/serial-discovery/1.3.1/*

$ ./arduino-cli board list
Error detecting boards: Error starting board discoveries: [discovery builtin:serial-discovery process not started: fork/exec /home/per/.arduino15/packages/builtin/tools/serial-discovery/1.3.1/serial-discovery: no such file or directory]
No boards found.

Arduino CLI version

nightly-20220218

Operating system

Windows, Linux

Operating system version

Windows 10, Ubuntu 20.04

Additional context

Originally reported at https://forum.arduino.cc/t/ide-2-0-lost-all-com-ports/960650


This situation is more problematic for Arduino IDE users, since the error message about the missing tool is not visible to them and they only notice the symptom of the IDE not seeing their ports.


It might seem unlikely for this interrupted installation to occur under real world conditions, but the equivalent issue with Boards Manager producing incomplete tools installations has been reported by users periodically ever since the introduction of Boards Manager, at sufficient volume for Arduino Support to consider it worth a Help Center article:

https://support.arduino.cc/hc/en-us/articles/360018444739-Error-file-does-not-exist-no-such-file-or-directory-system-cannot-find-the-file-specified

per1234 avatar Feb 18 '22 12:02 per1234

This now results in a cryptic panic that gives no clue about the cause to mere mortals:

$ arduino-cli version
arduino-cli  Version: 0.25.1-rc1 Commit: 436f0bb9 Date: 2022-07-23T14:28:16Z

$ rm ~/.arduino15/packages/builtin/tools/serial-discovery/1.3.2/*

$ ./arduino-cli board list
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4a51d9]

goroutine 35 [running]:
os.(*Process).signal(0xc000174770, {0x1034aa0, 0x15fd848})
	/usr/local/go/src/os/exec_unix.go:64 +0x39
os.(*Process).Signal(...)
	/usr/local/go/src/os/exec.go:138
os.(*Process).kill(...)
	/usr/local/go/src/os/exec_posix.go:68
os.(*Process).Kill(...)
	/usr/local/go/src/os/exec.go:123
github.com/arduino/arduino-cli/executils.(*Process).Kill(...)
	/home/per/Documents/deleteme/arduino-cli/executils/process.go:120
github.com/arduino/arduino-cli/arduino/discovery.(*PluggableDiscovery).killProcess(0xc0000b5480)
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discovery.go:268 +0xc9
github.com/arduino/arduino-cli/arduino/discovery.(*PluggableDiscovery).Quit(0xc0000b5480)
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discovery.go:381 +0xde
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).remove(0xc000070a20, {0xc000017dfe, 0x18})
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:82 +0xba
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).RunAll.func1(0xc0000b5480)
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:131 +0x71
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).parallelize.func1(0x1)
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:101 +0x68
created by github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).parallelize
	/home/per/Documents/deleteme/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:99 +0x1c5

The demo was done using Linux, but the problem also occurs on Windows.

per1234 avatar Jul 23 '22 14:07 per1234

Is this happening when there is only the directory without the executable?

cmaglie avatar Jul 25 '22 09:07 cmaglie

That is correct.

$ arduino-cli version
arduino-cli.exe  Version: 0.25.1-rc1 Commit: 436f0bb9 Date: 2022-07-22T15:47:42Z

$ arduino-cli board list
Port   Protocol Type              Board Name                FQBN             Core       
COM1   serial   Serial Port       Unknown
COM254 serial   Serial Port (USB) Unknown
COM3   serial   Serial Port       Unknown
COM52  serial   Serial Port (USB) Unknown
COM7   serial   Serial Port (USB) Arduino Mega or Mega 2560 arduino:avr:mega arduino:avr

$ rm ~/AppData/Local/Arduino15/packages/builtin/tools/serial-discovery/1.3.2/serial-discovery.exe

$ arduino-cli board list
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x8 pc=0xdd27cd]

goroutine 40 [running]:
os.(*Process).signal(0xc000150770, {0x196b990, 0x1f386e0})
        C:/Program Files/Go/src/os/exec_windows.go:49 +0x4d
os.(*Process).Signal(...)
        C:/Program Files/Go/src/os/exec.go:138
os.(*Process).kill(...)
        C:/Program Files/Go/src/os/exec_posix.go:68
os.(*Process).Kill(...)
        C:/Program Files/Go/src/os/exec.go:123
github.com/arduino/arduino-cli/executils.(*Process).Kill(...)
        E:/electronics/git-nobackup/arduino-cli/executils/process.go:120
github.com/arduino/arduino-cli/arduino/discovery.(*PluggableDiscovery).killProcess(0xc000985c00)
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discovery.go:268 +0xc9
github.com/arduino/arduino-cli/arduino/discovery.(*PluggableDiscovery).Quit(0xc000985c00)
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discovery.go:381 +0xde
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).remove(0xc0003782e0, {0x1716256, 0x18})
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:82 +0xba
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).RunAll.func1(0xc000985c00)
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:131 +0x71
github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).parallelize.func1(0x2e0031002e0032)
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:101 +0x68
created by github.com/arduino/arduino-cli/arduino/discovery/discoverymanager.(*DiscoveryManager).parallelize
        E:/electronics/git-nobackup/arduino-cli/arduino/discovery/discoverymanager/discoverymanager.go:99 +0x1c5

per1234 avatar Jul 25 '22 13:07 per1234

https://github.com/arduino/arduino-cli/pull/1814 fixed the panic I reported in my previous comment, but it did not resolve the feature request for Arduino CLI to recover from a situation where a discovery executable goes missing.

$ arduino-cli version
arduino-cli  Version: nightly-20220808 Commit: d0b2556 Date: 2022-08-08T01:35:05Z

$ rm ~/.arduino15/packages/builtin/tools/serial-discovery/1.3.2/*

$ arduino-cli board list
Error detecting boards: Error starting board discoveries: [discovery builtin:serial-discovery process not started: fork/exec /home/per/.arduino15/packages/builtin/tools/serial-discovery/1.3.2/serial-discovery: no such file or directory]
No boards found.

per1234 avatar Aug 08 '22 03:08 per1234

I'm reopening this issue because, although a nice improvement in this area, https://github.com/arduino/arduino-cli/pull/2107 is not a complete solution.

The most common conditions where the user's encounter this issue are that only the executable file is missing (most often due to being quarantined by the user's security software). https://github.com/arduino/arduino-cli/pull/2107 detects the broken installation state only when the tool release installation folder is empty (per the issue's original simplified demo, which cleared the entire folder), but we are including a LICENSE.txt file in the discovery and monitor tools installations. This means that if only the essential executable goes missing, the directory is not empty and the recovery mechanism is not activated:

$ arduino-cli version
arduino-cli.exe  Version: git-snapshot Commit: 2c2a5cc6 Date: 2023-04-22T13:21:59Z

$ ls "C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\serial-discovery"
1.4.0/

$ ls "C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\serial-discovery\\1.4.0"
LICENSE.txt  serial-discovery.exe*

$ rm "C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\serial-discovery\1.4.0\\serial-discovery.exe"

$ arduino-cli board list
Error starting discovery: discovery builtin:serial-discovery process not started: exec: "C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\builtin\\tools\\serial-discovery\\1.4.0\\serial-discovery": file does not exist
No boards found.

per1234 avatar Apr 22 '23 13:04 per1234

May I suggest installing in a temporary directory and then only after everything has been extraced copy it over to the final installation path?

If even a single file copy fails abort the whole process and remove the ones that have been copied.

Also I's suggest blocking the possibility of interrupting the execution to prevent it being interrupted during steps that would leave files behind.

silvanocerza avatar Apr 26 '23 15:04 silvanocerza

Also to check if the installation is valid I'd create a checksum of the whole folder when it's first installed. Then in IsInstalled() compare it with the current content checksum to verify its integrity, if they differ it's not installed.

silvanocerza avatar Apr 26 '23 15:04 silvanocerza

May I suggest installing in a temporary directory and then only after everything has been extraced copy it over to the final installation path?

The issue here is that the copy is successful, but the antivirus will move the file into quarantine after the installation has been completed.

Also to check if the installation is valid I'd create a checksum of the whole folder when it's first installed. Then in IsInstalled() compare it with the current content checksum to verify its integrity, if they differ it's not installed.

This is an expensive operation to do at every run of the CLI....

cmaglie avatar Apr 27 '23 08:04 cmaglie

The issue here is that the copy is successful, but the antivirus will move the file into quarantine after the installation has been completed.

We could add an after install check to verify the integrity and warn the user that installation wasn't successfull cause of the antivirus maybe.

Even using the same checksum strategy, assuming the file is removed immediately after the copy.

This is an expensive operation to do at every run of the CLI....

Fair enough, less expensive and frustrating than a bad UX for me though.

Maybe do it only when the CLI is trying to run a certain tool, and act accordingly.

silvanocerza avatar Apr 27 '23 08:04 silvanocerza

Given the very simple format of the discoveries, I guess that just checking if the executable is there is enough.

cmaglie avatar Apr 27 '23 08:04 cmaglie

Fair enough, less expensive and frustrating than a bad UX for me though.

UX wise you are adding a fixed delay to 100% of the users to solve an issue that 0.01% are experiencing...

cmaglie avatar Apr 27 '23 08:04 cmaglie

Given the very simple format of the discoveries, I guess that just checking if the executable is there is enough.

Yeah, if the issue is present only for discoveries it would make sense to check only for those.

UX wise you are adding a fixed delay to 100% of the users to solve an issue that 0.01% are experiencing...

True that, I have no metrics either way. 😉

silvanocerza avatar Apr 27 '23 13:04 silvanocerza