I got my serial port modem control lights to blink and wait for 
interrupts using a SIIG 16550 UART PCI card. It's an old program, but 
FreePascal helps me read it still. The trick was to use un-named pipes 
and forked waiting listener processes. Forget the "threads" confusion. 
Basically, 5 processes. Four to separately listen to modem control lines 
DSR, CTS, DCD, RNG. And one to manage all the setup and interface.

But I really like old fashioned FreePascal (TurboPascal) strings and 
reading and writing. Forget the null terminated C string glop. And the 
Pascal tools work beautifully on the serial port.

Since Pascal text reading and writing each require their own open file 
descriptor, and the Linux ioctl for modem control needs the C generated 
file descriptor, I was stumped; "What is the file descriptor?"

Luckily, I have (at least) 2 books, "The Design of the Unix Operating 
System" by Maurice Bach and "The Linux Process Manager" by John 
O'Gorman. It seems Unix inventors already thought of this situation. And 
when you think about it, all the glop on your Linux box starts from one 
process. Only an old Minnesota penguin would enjoy learning about user 
file descriptor table vs. file table vs. inode table.

Unix and Linux must now be regarded as "critical infrastructure." These 
systems have outlasted cars, roofs, furnace. The available documentation 
is extraordinary. Old can be very good.