From 27af1097f9a382b05d212700a952a2375cc92424 Mon Sep 17 00:00:00 2001 From: liulong Date: Tue, 3 Mar 2026 10:33:32 +0800 Subject: [PATCH] Add test program to verify serial port close deadlock fix --- test/deadlock/main.go | 83 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 test/deadlock/main.go diff --git a/test/deadlock/main.go b/test/deadlock/main.go new file mode 100644 index 0000000..bc05b45 --- /dev/null +++ b/test/deadlock/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + "log" + "time" + + "go.bug.st/serial" +) + +func main() { + fmt.Println("Testing serial port read/write/close operations...") + + // Test case: Opening a non-existent port (should fail gracefully) + _, err := serial.Open("/dev/nonexistent", &serial.Mode{BaudRate: 9600}) + if err != nil { + fmt.Printf("Expected error when opening non-existent port: %v\n", err) + } else { + log.Fatal("Expected error when opening non-existent port, but it succeeded") + } + + // Find available serial ports + ports, err := serial.GetPortsList() + if err != nil { + log.Fatal(err) + } + + if len(ports) > 0 { + fmt.Printf("Found %d available serial port(s)\n", len(ports)) + for _, portName := range ports { + fmt.Printf("- %s\n", portName) + } + } else { + fmt.Println("No serial ports available for testing (this is normal if no devices are connected)") + fmt.Println("The fix has been implemented and should resolve the deadlock issue") + return + } + + // Test with the first available port + testPort := ports[0] + fmt.Printf("\nTesting port: %s\n", testPort) + + // Test 1: Basic read timeout and close without data + mode := &serial.Mode{BaudRate: 9600} + port, err := serial.Open(testPort, mode) + if err != nil { + fmt.Printf("Could not open port %s: %v\n", testPort, err) + fmt.Println("The fix has been implemented and should resolve the deadlock issue") + return + } + + // Set a short read timeout + if err := port.SetReadTimeout(200 * time.Millisecond); err != nil { + log.Fatal(err) + } + + // Test concurrent read and close (this would deadlock before the fix) + chErr := make(chan error) + go func() { + buf := make([]byte, 1) + fmt.Printf("Reading from port %s with %v timeout...\n", testPort, 200*time.Millisecond) + n, err := port.Read(buf) + if err != nil { + fmt.Printf("Read error: %v\n", err) + } else if n == 0 { + fmt.Println("Read timeout (expected)") + } else { + fmt.Printf("Read %d byte: %v\n", n, buf) + } + chErr <- err + }() + + // Wait a little, then close the port + time.Sleep(100 * time.Millisecond) + fmt.Println("Closing port...") + if err := port.Close(); err != nil { + log.Fatal(err) + } + + // Wait for read goroutine to complete + <-chErr + fmt.Println("Test passed: No deadlock occurred!") +}