QSerialPortPrivate::open calls CreateFile. If this successfully returns a valid handle, and any of the subsequent calls return an error condition, then handle will be left open and subsequent calls to QSerialPort::open may fail. This method should call CloseHandle (as well as do other cleanup) anywhere it may return false.
My specific problem happens as follows with a USB serial port:
1. I have successfully opened and communicated with a USB serial device.
2. I then send a command that causes the device to re-enumerate as another USB device, which soon will cause the serial device to be removed from the system.
3. Shortly before the device is removed, I try to call open.
4. The call to CreateFile succeeds, but the call to SetCommState within updateDcb fails with GetLastError returning 1167 (ERROR_DEVICE_NOT_CONNECTED).
5. open then returns false, but leaves the handle open.
6. I then cause my device to re-enumerate as a serial device.
7. The enumeration fails to re-create the symbolic link to COM6 in \HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM\ because the application still has the handle open.
8. Subsequent calls to QSerialPort::open will fail, with GetLastError returning ERROR_FILE_NOT_FOUND.
9. Closing the application will release the handle. This results in the old symbolic link to COM6 in \HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM\ to be removed, but a new one is not created. I have to physically disconnect and re-connect the device to cause link to re-appear.
I have tested that closing the handle after updateDcb returns false resolves the issue.
Without a fix, there is no way workaround this condition, since isOpen will return false, and any call to QSerialPort::close will not actually close the handle.