jacobsa / go-serial

A Go library for dealing with serial ports.
Apache License 2.0
626 stars 120 forks source link

Help with preventing program from panicking out if no USB is found #33

Closed bravecorvus closed 6 years ago

bravecorvus commented 6 years ago

I am currently utilizing your package in an clock program that sends time over serial USB. I want to ensure that the program can "attempt" to open the device via serial USB, but ignore the case when the Arduino is not connected to my Raspberry Pi via USB.

I am declaring the serial.OpenOptions{} with the following code.

    Options = serial.OpenOptions{
    PortName:        nixie.FindArduino(),
    BaudRate:        115200,
    DataBits:        8,
    StopBits:        1,
    MinimumReadSize: 4,
    }

Where nixie.FindArduino() looks in /dev for the file "ttyACM0", and returns an empty string if it cannot find the device.

Next, I try to use the following code to open the serial USB tty connection (but still open a temporary file if no such file is found)

    var Port io.ReadWriteCloser
    if Options.PortName != "" {
        Port, err := serial.Open(Options)
        if err != nil {
            foundNixie = false
        } else {
            foundNixie = true
        }
        defer Port.Close()
    } else {
        Port, _ := os.OpenFile("tempfile", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0600)
        defer Port.Close()
    }

However, this program will panic out whenever I try to send strings over serial USB.

                b := []byte("TRIAL STRING")
                _, err := Port.Write(b)
                if err != nil {
                    log.Fatalf("Port.Write: %v", err)
                }
        /home/pi/go/src/github.com/gilgameshskytrooper/prometheus/prometheus.go:231 +0x110
github.com/robfig/cron.FuncJob.Run(0x10717cb0)
        /home/pi/go/src/github.com/robfig/cron/cron.go:92 +0x1c
github.com/robfig/cron.(*Cron).runWithRecovery(0x107189f0, 0x3ec300, 0x10717cb0)
        /home/pi/go/src/github.com/robfig/cron/cron.go:165 +0x54
created by github.com/robfig/cron.(*Cron).run
        /home/pi/go/src/github.com/robfig/cron/cron.go:199 +0x554

On the other hand, the method I was using previously of just declaring and assigning the Port variable works flawlessly when the USB device is connected, but immediately fails when I try to write anything if the device is not connected.

    Options := serial.OpenOptions{
    PortName:        nixie.FindArduino(),
    BaudRate:        115200,
    DataBits:        8,
    StopBits:        1,
    MinimumReadSize: 4,
    }

        Port, err := serial.Open(Options)
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x12fac]

goroutine 1 [running]:
panic(0x2c6568, 0x1070c010)
        /usr/lib/go-1.7/src/runtime/panic.go:500 +0x33c
main.main()
        /home/pi/go/src/github.com/gilgameshskytrooper/prometheus/prometheus.go:209 +0x190

How can I write the program so that the program can continue to run even if the serial device cannot be found?

jacobsa commented 6 years ago

You're missing the most important thing here: the output of the log.Fatalf call. What was the error?

That said, if I understand your description correctly then this is unlikely to be a bug in the serial package, but rather your wrapper code.