This question have been answered, see at the end and comments.
Why is it that libserial SerialStream throws "Bad file descriptor" when opening a stream?
This question have been been raised several times on different forums including here. None of those answer solves my problem tough.
Running the simple code below makes iostream (parent to SerialStream) throw a "Bad file descriptor".
I have isolated the problem as much as possible as presented here. The setup is:
- Lubunto 20.04 in a WmWare player 16 (latest)
- The code is run in Eclipse as a managed project
- The linked library is serial (libserial)
- The serial port is connected to a ftdi usb-to-serial dongle
- libserial is at v 1.0.0.something
- gcc c++14
- Compiles and links without errors and warnings
- Debugging and stepping works
#include <libserial/SerialPort.h>
#include <libserial/SerialStream.h>
#include <iostream>
using namespace std;
using namespace LibSerial;
int main() {
SerialPort aPort;
SerialStream aStream;
try {
aPort.Open("/dev/ttyUSB0");
aStream.Open("/dev/ttyUSB0"); // <-- This fails
} catch (exception& e) {
cout << e.what() << endl;
}
return 0;
}
Make output
21:46:34 **** Build of configuration Debug for project test **** make
all Building file: ../src/test.cpp Invoking: GCC C++ Compiler g++
-std=c++1y -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.o" -o "src/test.o" "../src/test.cpp" Finished building: ../src /test.cpp Building target: test Invoking:
GCC C++ Linker g++ -o "test" ./src/test.o -lserial Finished
building target: test 21:46:35 Build Finished. 0 errors, 0 warnings.
(took 108ms)
Running this yields "Bad file descriptor" out of e.what() and thrown by aStream.Open("/dev/ttyUSB0"); Observe that aPort.Open("/dev/ttyUSB0"); makes it through.
So some other fact are also:
- Connecting gtkterm to "/dev/ttyUSB0" works fine, physical output verified
- Testing for the device name and user permissions gives:
agda@agda-virtual:~$ dmesg | grep tty
[ 0.073253] printk: console [tty0] enabled [ 0.755452] 00:05: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A [ 0.794338] tty tty4: hash matches [ 3.909769] usb 2-2.1: FTDI USB Serial Device converter now attached to ttyUSB0
agda@agda-virtual:~$ groups agda
agda : agda adm dialout cdrom sudo dip plugdev lpadmin sambashare
agda@agda-virtual:~$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Mar 24 18:56 /dev/ttyUSB0
My conclusions from this is, the serial dongle is mounted and works as "/dev/ttyUSB0". The permissions are correct and the groups are correct.
The call tree don't give my any clues:
Thread #1 [test] 4978 [core: 2] (Suspended : Signal : SIGABRT:Aborted) __GI_raise() at raise.c:50 0x7ffff7bc818b
__GI_abort() at abort.c:79 0x7ffff7ba7859
0x7ffff7e2d951
0x7ffff7e3947c
std::terminate() at 0x7ffff7e394e7
__cxa_rethrow() at 0x7ffff7e397ed
0x7ffff7f7a28a
main() at test.cpp:19 0x5555555553f6
What am I missing here?
And if I cannot solve this one on my particular system, any suggestions on other ways to go for an USB async communication is appreciated.
Answer: As stated by codo in the comments, it is not possible to open the same serial channel twice. I've corrected this and it now works fine in the real code. This was a mistake caused by reading the documentation sloppy and instead copy code from an bad example.
For anybody running into the same problem: The SerialPort and SerialStream are two alternative methods of access to a serial port using libserial. Use one of them.
file descriptor
. /dev/ttyUSB0 is a filename, or more precisely, a device node. A file descriptor is an integer number returned by an open() syscall. Check the procedure prototype. – sawdust