@@ -324,13 +324,23 @@ func (l *ListViewImpl) listenToTaskUpdates() {
324
324
l .mu .Lock ()
325
325
log .Infof ("acquired lock before re-creating listview" )
326
326
if recreateView {
327
+ if l .listView != nil {
328
+ destroyListviewErr := l .listView .Destroy (l .ctx )
329
+ if destroyListviewErr != nil {
330
+ // ignoring the error and re-creating the list view
331
+ log .Errorf ("failed to destroy listview object. err: %v" , destroyListviewErr )
332
+ } else {
333
+ log .Info ("successfully destroyed existing listview" )
334
+ }
335
+ }
327
336
log .Info ("re-creating the listView object" )
328
337
err := l .createListView (l .ctx , nil )
329
338
if err != nil {
330
339
log .Errorf ("failed to create a ListView. error: %+v" , err )
331
340
l .mu .Unlock ()
332
341
continue
333
342
}
343
+ log .Info ("successfully created listview" )
334
344
335
345
filter = getListViewWaitFilter (l .listView )
336
346
l .waitForUpdatesContext , l .waitForUpdatesCancelFunc = context .WithCancel (context .Background ())
@@ -395,12 +405,19 @@ func (l *ListViewImpl) listenToTaskUpdates() {
395
405
396
406
// reportErrorOnAllPendingTasks returns failure to all pending tasks in the map in case of vc failure
397
407
func (l * ListViewImpl ) reportErrorOnAllPendingTasks (err error ) {
408
+ log := logger .GetLogger (context .Background ())
398
409
for _ , taskDetails := range l .taskMap .GetAll () {
399
410
result := TaskResult {
400
411
TaskInfo : nil ,
401
412
Err : err ,
402
413
}
403
- taskDetails .ResultCh <- result
414
+ // Non-blocking send
415
+ select {
416
+ case taskDetails .ResultCh <- result :
417
+ log .Infof ("reported error for task %+v" , taskDetails .Reference )
418
+ default :
419
+ log .Warnf ("failed to report error for task %+v: channel blocked" , taskDetails .Reference )
420
+ }
404
421
}
405
422
}
406
423
@@ -431,8 +448,16 @@ func (l *ListViewImpl) processTaskUpdate(prop types.PropertyChange) {
431
448
result .TaskInfo = & taskInfo
432
449
result .Err = nil
433
450
}
434
-
435
- taskDetails .ResultCh <- result
451
+ // Use a non-blocking send to prevent deadlocks when multiple goroutines
452
+ // try to send to the same channel (e.g., due to duplicate task updates from vSphere)
453
+ select {
454
+ case taskDetails .ResultCh <- result :
455
+ log .Infof ("Successfully sent task result for task %+v" , taskInfo .Task )
456
+ default :
457
+ // Channel is full/blocked, which means another goroutine already sent the result
458
+ // This can happen when vSphere sends duplicate task update events
459
+ log .Warnf ("result channel full for task %+v, ignoring duplicate update" , taskInfo .Task )
460
+ }
436
461
}
437
462
438
463
// RemoveTasksMarkedForDeletion goes over the list of tasks in the map
0 commit comments