Просмотр исходного кода

Fix: interrupt blocked tapdanceDialer.DialContext on cancel

Rod Hynes 7 лет назад
Родитель
Сommit
45bc0c9c7c
1 измененных файлов с 20 добавлено и 0 удалено
  1. 20 0
      psiphon/common/tapdance/tapdance.go

+ 20 - 0
psiphon/common/tapdance/tapdance.go

@@ -254,7 +254,27 @@ func Dial(
 		TcpDialer: manager.dial,
 	}
 
+	// If the dial context is cancelled, use dialManager to interrupt
+	// tapdanceDialer.DialContext. See dialManager comment explaining why
+	// tapdanceDialer.DialContext may block even when the input context is
+	// cancelled.
+	dialComplete := make(chan struct{})
+	go func() {
+		select {
+		case <-ctx.Done():
+		case <-dialComplete:
+		}
+		select {
+		// Prioritize the dialComplete case.
+		case <-dialComplete:
+			return
+		default:
+		}
+		manager.close()
+	}()
+
 	conn, err := tapdanceDialer.DialContext(ctx, "tcp", address)
+	close(dialComplete)
 	if err != nil {
 		manager.close()
 		return nil, common.ContextError(err)