July 16, 2018 at 8:19 pm #2149
I’ve moved my trueRNG3 to a raspberry pi. I’m not configuring it to feed /dev/random – I’m opening it as a /dev/serial/by-id/… and doing timed reads from it. The goal is to collect 200 bytes from it periodically.
This should be trivial, but even doing repeated reads, I sometimes get less than 200 bytes in 500ms. And that can’t possibly be right.
Is this a symptom of a dying device? Is it generating mostly all 0′s internally, whitening them, and getting virtually nothing to output? Or is it not as simple as doing read()? It was that simple on Windows…October 16, 2018 at 11:15 am #2210
I realize this is an old thread, we had some issues with the web site getting exploited and all the settings messed up so we weren’t getting notifications.
Are you still having issues with this ?October 16, 2018 at 11:29 am #2211
I’m using ppoll to determine when data is available, and then read it. Frequently, ppoll announces that data is available but read returns 0 bytes. My code assumes that was a problem and stopped reading. The workaround is to do a sched-yield before the read. I don’t know why that helps but it does.October 16, 2018 at 1:51 pm #2212
Hmm, I assume that ppoll is returning a positive number ? What is your timeout on ppoll ?
You are using the udev script correct ? What happens if you don’t use your program, you just do something like cat /dev/TrueRNG > /tmp/file or using pv instead of cat (to see the rate) ? I’m just trying to make sure the TrueRNG is operating normally.
The only signal that would stop the flow on the TrueRNG is the DTR signal. If you are some how toggling DTR (on USB it’s virtualized and not a hardware pin but it still works) it will stop/start the flow. The random number generator never stops generating, but if DTR goes away it throws it in the trash instead of over the USB bus.October 16, 2018 at 6:34 pm #2213
My code works by specifying a number of bytes to read and a timeout. It does a ppoll() using POLLIN | POLLERR | POLLHUP, and returns an error if that returns <= 0. Otherwise it does a single byte read (that’s all that’s guaranteed to work after a ppoll()), marks off another byte read, and if it’s not done, it recomputes the remaining time and goes around again. It’s very inefficient, but I use the same “timed read” code for sockets and other devices, not just the trueRNG, and that’s what works for sockets.
At first I didn’t realize it was getting 0 back from read on a TrueRNG, which caused it to abandon the loop early, so I thought I was getting just a few bytes after a long wait. But the problem isn’t the rate, it’s the unexpected 0 from read.
If ppoll() says there’s something, I should either get a character or EOF, and I wouldn’t expect an EOF from a trueRNG. I changed the code to 1) do a sched_yield before the read, which cut down the read failures (possibly to none). To be sure I also added a check for read()==0, which now simply causes a usleep(100) and goes around again. At this time all the “timed reads” work, and I don’t think it’s hitting the usleep(). I did a rpi-update recently, but sorry I can’t interrupt the code at this time to try taking out the sched_yield.
My initial guess was some sort of confusion in some driver – this is a quad core pi and maybe some caching was mishandled in driverland. read() certainly should never return 0 after ppoll() says there’s something happening.
I do (deliberately) turn DTR on and off around reads, just to diminish meaningless traffic, but taking that code out didn’t seem to affect the bug. For the trueRNG the code happens to ask for 384 bytes in 750ms; I would never have expected to fail.October 17, 2018 at 12:40 pm #2214
So while googling for possible causes, I found your stackoverflow post
If sched_yield fixes your issue then I would say go with that. One thing I can think of is to either try this code on a PC (take out the raspberry pi aspect).
Another other would be check your termios settings (tcsetattr/getattr) (this is why I asked about using the udev script). Since the TrueRNG outputs full binary, If the termios settings aren’t raw, and its set to canonical mode, then I believe the tty would eat the EOF character, alert ppoll, but cause read() to return 0 bytes read (according to https://stackoverflow.com/questions/358342/canonical-vs-non-canonical-terminal-input).
Of other note, make sure you don’t have modemmanager package installed, we’ve seen cases where it will open the port, change the tty settings, and do stuff while you are using the port (It’s noted somewhere in the docs or forums). We added some stuff to udev to disable it, but there is a case where newer OS updates don’t allow that setting or something any more.October 19, 2018 at 12:16 pm #2215
Well, that’s embarrassing. I changed the termios settings to raw, used ioctl to determine how many bytes were available to read, and I stopped getting 0 byte reads. I have no idea why the sched_yield appeared to change the behaviour. Many apologies.October 23, 2018 at 3:47 pm #2216
The only thing I can think of why sched_yield appeared to fix it, was by causing a delay, and another byte was actually available for reading (that wasn’t EOF), while it did drop the EOF char and notify you. but the problem of termios not being raw was still there.
Anyway, glad the problem is resolved.
You must be logged in to reply to this topic.