I have a program running as root on Linux, talking to a tty (actually an LCD implemented as a tty). The device for what it's worth is /dev/ttyUSB0. I'd like to have my program that writes to this device be able to have exclusive access to the device, so as to not have any interference from other instances of the program running at the same time.
I see that there's a ioctl option called TIOCEXCL which will prevent additonal open's of the device to wit "multiple open() calls to the same file will succeed unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned processes." I tested this and it works just as advertised: if a non-root user tries to open /dev/ttyUSB0 (once I changed the permissions) then the open fails with something like "device busy" and if a root user tries to open it, it works.
What I ideally want is a way to this exclusive access to the tty to work for root users. So I'd have multiple root users using the program that writes to the LCD, but somehow their access to the LCD (tty) would be serialized. Apparently the TIOCEXCL ioctl option will not work for me since it doesn't stop root users from opening an already-opened tty device.
I guess there are a number of options here, but I am reaching out to all ya'll to see if you might have other thoughts or suggestions.
Maybe I'm missing something about using TIOCEXCL...
Maybe there's some other way via open() or ioctl() or what-not to get exclusive access.
If there was some way I could detect that some other process has the device open, I could just wait and retry. I know about lsof but I'm loath to invoke it from inside this program just to learn this. And there are race conditions with that. (Maybe I can get over that? :) )
I could implement locking like apparently used to be done to get exclusive access to tty devices.
Update 1:
Since the only program writing to the LCD device is mine, I am inclined to do something like the following (pseudo-code) to lock inside the code:
f = open("/dev/ttyUSB0", O_RDWR)
flock(f, LOCK_EX)
// do any ioctl's, etc.
// do any write's
// sleep a tad to not flash messages too fast on LCD
nanosleep({0, 250000000}, NULL)
flock(f, LOCK_UN)
close(f)