Skip to content

Commit e9e5fbd

Browse files
committed
Before returning from upload, check if the port is still alive
Now the upload detects cases when the upload port is "unstable", i.e. the port changes even if it shouldn't (because the wait_for_upload_port property in boards.txt is set to false). This change should make the upload process more resilient.
1 parent f8394fb commit e9e5fbd

File tree

1 file changed

+37
-26
lines changed

1 file changed

+37
-26
lines changed

Diff for: commands/upload/upload.go

+37-26
Original file line numberDiff line numberDiff line change
@@ -381,20 +381,18 @@ func runProgramAction(pme *packagemanager.Explorer,
381381
uploadCtx, uploadCompleted := context.WithCancel(context.Background())
382382
defer uploadCompleted()
383383

384-
// By default do not return any new port but if there is an
385-
// expected port change then run the detector.
386-
updatedUploadPort := f.NewFuture[*discovery.Port]()
387-
if uploadProperties.GetBoolean("upload.wait_for_upload_port") {
388-
watcher, err := pme.DiscoveryManager().Watch()
389-
if err != nil {
390-
return nil, err
391-
}
392-
defer watcher.Close()
393-
394-
go detectUploadPort(uploadCtx, port, watcher.Feed(), updatedUploadPort)
395-
} else {
396-
updatedUploadPort.Send(nil)
384+
// Start the upload port change detector.
385+
watcher, err := pme.DiscoveryManager().Watch()
386+
if err != nil {
387+
return nil, err
397388
}
389+
defer watcher.Close()
390+
updatedUploadPort := f.NewFuture[*discovery.Port]()
391+
go detectUploadPort(
392+
uploadCtx,
393+
port, watcher.Feed(),
394+
uploadProperties.GetBoolean("upload.wait_for_upload_port"),
395+
updatedUploadPort)
398396

399397
// Force port wait to make easier to unbrick boards like the Arduino Leonardo, or similar with native USB,
400398
// when a sketch causes a crash and the native USB serial port is lost.
@@ -514,18 +512,19 @@ func runProgramAction(pme *packagemanager.Explorer,
514512
uploadCompleted()
515513
logrus.Tracef("Upload successful")
516514

517-
updatedPort := updatedUploadPort.Await()
518-
if updatedPort == nil {
519-
return userPort, nil
520-
}
521-
return updatedPort.ToRPC(), nil
515+
return updatedUploadPort.Await().ToRPC(), nil
522516
}
523517

524-
func detectUploadPort(uploadCtx context.Context, uploadPort *discovery.Port, watch <-chan *discovery.Event, result f.Future[*discovery.Port]) {
518+
func detectUploadPort(
519+
uploadCtx context.Context,
520+
uploadPort *discovery.Port, watch <-chan *discovery.Event,
521+
waitForUploadPort bool,
522+
result f.Future[*discovery.Port],
523+
) {
525524
log := logrus.WithField("task", "port_detection")
526525
log.Tracef("Detecting new board port after upload")
527526

528-
var candidate *discovery.Port
527+
candidate := uploadPort.Clone()
529528
defer func() {
530529
result.Send(candidate)
531530
}()
@@ -538,7 +537,13 @@ func detectUploadPort(uploadCtx context.Context, uploadPort *discovery.Port, wat
538537
log.Error("Upload port detection failed, watcher closed")
539538
return
540539
}
541-
log.WithField("event", ev).Trace("Ignored watcher event before upload")
540+
if candidate != nil && ev.Type == "remove" && ev.Port.Equals(candidate) {
541+
log.WithField("event", ev).Trace("User-specified port has been disconnected, forcing waiting for upload port")
542+
waitForUploadPort = true
543+
candidate = nil
544+
} else {
545+
log.WithField("event", ev).Trace("Ignored watcher event before upload")
546+
}
542547
continue
543548
case <-uploadCtx.Done():
544549
// Upload completed, move to the next phase
@@ -549,19 +554,25 @@ func detectUploadPort(uploadCtx context.Context, uploadPort *discovery.Port, wat
549554
// Pick the first port that is detected after the upload
550555
desiredHwID := uploadPort.HardwareID
551556
timeout := time.After(5 * time.Second)
557+
if !waitForUploadPort {
558+
timeout = time.After(time.Second)
559+
}
552560
for {
553561
select {
554562
case ev, ok := <-watch:
555563
if !ok {
556564
log.Error("Upload port detection failed, watcher closed")
557565
return
558566
}
559-
if ev.Type == "remove" && candidate != nil {
560-
if candidate.Equals(ev.Port) {
561-
log.WithField("event", ev).Trace("Candidate port is no more available")
562-
candidate = nil
563-
continue
567+
if candidate != nil && ev.Type == "remove" && candidate.Equals(ev.Port) {
568+
log.WithField("event", ev).Trace("Candidate port is no more available")
569+
candidate = nil
570+
if !waitForUploadPort {
571+
waitForUploadPort = true
572+
timeout = time.After(5 * time.Second)
573+
log.Trace("User-specified port has been disconnected, now waiting for upload port, timeout exteneded by 5 seconds")
564574
}
575+
continue
565576
}
566577
if ev.Type != "add" {
567578
log.WithField("event", ev).Trace("Ignored non-add event")

0 commit comments

Comments
 (0)