msg125316 - (view) |
Author: Michal Čihař (nijel) * |
Date: 2011-01-04 13:42 |
Currently if /dev/urandom does not provide any data, unradom() call is just stuck infinitely waiting for data.
I actually faced this issue when /dev/urandom was empty regular file (due to bug in pbuilder, but I don't think it matters how it did happen) and urandom() call just hang. I think it would be much saner in such case to throw an error and let user know that something it wrong than waiting infinitely.
|
msg125318 - (view) |
Author: Antoine Pitrou (pitrou) *  |
Date: 2011-01-04 13:49 |
This would change semantics of the library call, though.
I see two possible solutions:
- do nothing and let users tackle the issue if necessary (e.g. by calling open() themselves and using select() on the resulting fd)
- add an optional "blocking" parameter to os.urandom() that, if False, would return None when no data is available
|
msg125320 - (view) |
Author: Michal Čihař (nijel) * |
Date: 2011-01-04 13:59 |
Well in this particular case (/dev/urandom is regular file), it might make sense to simply raise NotImplementedError
|
msg125321 - (view) |
Author: Antoine Pitrou (pitrou) *  |
Date: 2011-01-04 14:01 |
> Well in this particular case (/dev/urandom is regular file), it might
> make sense to simply raise NotImplementedError
IMO it would be quite fragile to try to detect regular files vs special
files. I suppose you noticed the issue quite quickly anyway, since you
had the blocking issue.
|
msg125322 - (view) |
Author: Georg Brandl (georg.brandl) *  |
Date: 2011-01-04 14:06 |
Is it really necessary to do something about this? /dev/urandom being a regular file is clearly a bug in your system configuration, and I don't want to know what all the other programs will do that rely on it...
|
msg125323 - (view) |
Author: Charles-François Natali (neologix) *  |
Date: 2011-01-04 14:10 |
From the documentation:
"This function returns random bytes from an OS-specific randomness source."
In your case, this problem shows up because of an OS misconfiguration : in that case, the behaviour is undefined (not much Python can do about it). Note that since /dev/urandom is used, with a properly configured system, this should never block (contrarily to /dev/random which might block until enough entropy has been gathered).
|
msg125324 - (view) |
Author: Michal Čihař (nijel) * |
Date: 2011-01-04 14:11 |
Yes, it was blocking, but deep in some program (which was actually called by dpkg postinst script), so it took some time to figure out.
I don't think it's that fragile to figure out whether it is regular file using os.path.isfile.
Indeed it was bug in a system, but actually this was only thing which got stuck because of it.
|
msg125325 - (view) |
Author: Antoine Pitrou (pitrou) *  |
Date: 2011-01-04 14:13 |
> Note that since /dev/urandom is used, with a properly configured
> system, this should never block
Ok, suggesting closing then.
|
msg125362 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2011-01-04 21:08 |
I wonder why reading from /dev/urandom has a loop in the first place, though - isn't it guaranteed that you can read as many bytes as you want in one go? This goes back to #934711, and apparently, even the original patch had the loop - for reasons that got never questioned.
|
msg125365 - (view) |
Author: R. David Murray (r.david.murray) *  |
Date: 2011-01-04 21:40 |
Agreed that the original issue is invalid. So either the title should be changed so it can be used to address Martin's question, or it should be closed.
|
msg125368 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2011-01-04 21:54 |
Closing it. It seems that people feel more safe when urandom loops until it has enough data (see http://stackoverflow.com/questions/4598507/dev-urandom-maximum-size/4598534#4598534). I might still pursue this idea, but in a different issue.
|
msg125369 - (view) |
Author: Charles-François Natali (neologix) *  |
Date: 2011-01-04 21:58 |
> Martin v. Löwis <martin@v.loewis.de> added the comment:
>
> I wonder why reading from /dev/urandom has a loop in the first place, though - isn't it guaranteed that you can read as many bytes as you want in one go? This goes back to #934711, and apparently, even the original patch had the loop - for reasons that got never questioned.
>
I found surprising that a read from /dev/urandom would be
uninterruptible, so I digged a little, and found this mail from 1998:
[patch] fix for urandom read(2) not interruptible
http://marc.info/?l=bugtraq&m=91495921611500&w=2
"It's a bug in random.c that doesn' t check for signal pending inside the
read(2) code, so you have no chance to kill the process via signals until
the read(2) syscall is finished, and it could take a lot of time before
return, if the buffer given to the read syscall is very big..."
I've had a quick look at the source code, and indeed, read(2) from
/dev/urandom can now be interrupted by a signal, so looping seems to
be justified.
> ----------
> nosy: +loewis
> status: pending -> open
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue10824>
> _______________________________________
>
|
msg125376 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2011-01-04 22:37 |
> "It's a bug in random.c that doesn' t check for signal pending inside the
> read(2) code, so you have no chance to kill the process via signals until
> the read(2) syscall is finished, and it could take a lot of time before
> return, if the buffer given to the read syscall is very big..."
>
> I've had a quick look at the source code, and indeed, read(2) from
> /dev/urandom can now be interrupted by a signal, so looping seems to
> be justified.
No: if read(2) is interrupted, no data is returned, and exception is
raised. So it won't loop in that case, but raise the exception out of
urandom also (which is the right thing to do).
|
msg125519 - (view) |
Author: Charles-François Natali (neologix) *  |
Date: 2011-01-06 08:18 |
> Martin v. Löwis <martin@v.loewis.de> added the comment:
>
>> "It's a bug in random.c that doesn' t check for signal pending inside the
>> read(2) code, so you have no chance to kill the process via signals until
>> the read(2) syscall is finished, and it could take a lot of time before
>> return, if the buffer given to the read syscall is very big..."
>>
>> I've had a quick look at the source code, and indeed, read(2) from
>> /dev/urandom can now be interrupted by a signal, so looping seems to
>> be justified.
>
> No: if read(2) is interrupted, no data is returned, and exception is
> raised. So it won't loop in that case, but raise the exception out of
> urandom also (which is the right thing to do).
>
(Sorry for being a little off-topic, but since there's not dedicated thread)
Try with this:
dd if=/dev/urandom of=/dev/null bs=100M count=1
Then, in another terminal:
pkill -USR1 -xn dd
You'll see that read returns less that 100M bytes when interrupted.
You can also try with the following python code:
---
import os
d = os.open('/dev/urandom', os.O_RDONLY)
data = os.read(d, 1 << 28)
os.close(d)
print('read %d bytes' % len(data))
---
and in another terminal
pkill -STOP -xn python
then
pkill -CONT -xn python
Same thing, read returns less bytes than requested.
Anyway, since /dev/urandom is not part of any standard (AFAIK), it's
probably better to use the common idiom
while len(data) < expected:
read(expected - len(data))
So we're sure it won't break under some systems/conditions.
Cheers
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue10824>
> _______________________________________
>
|
msg125601 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2011-01-06 22:53 |
> You'll see that read returns less that 100M bytes when interrupted.
I see.
> while len(data) < expected:
> read(expected - len(data))
>
> So we're sure it won't break under some systems/conditions.
I think this is not quite the idiom we should use if we want to deal
with signals: if read() returns an empty string, we have hit end-of-file.
If there is a signal before anything is read, we should catch the
exception and continue reading (which the loop doesn't do, either).
OTOH, if the signal was due to a user interrupt, we should raise an
exception, anyway, IMO - even if we've read some data already.
|
|
Date |
User |
Action |
Args |
2022-04-11 14:57:10 | admin | set | github: 55033 |
2011-01-06 22:53:18 | loewis | set | nosy:
loewis, georg.brandl, nijel, pitrou, r.david.murray, neologix messages:
+ msg125601 |
2011-01-06 08:18:41 | neologix | set | nosy:
loewis, georg.brandl, nijel, pitrou, r.david.murray, neologix messages:
+ msg125519 |
2011-01-04 22:37:40 | loewis | set | nosy:
loewis, georg.brandl, nijel, pitrou, r.david.murray, neologix messages:
+ msg125376 |
2011-01-04 21:58:17 | neologix | set | nosy:
loewis, georg.brandl, nijel, pitrou, r.david.murray, neologix messages:
+ msg125369 |
2011-01-04 21:54:37 | loewis | set | status: open -> closed nosy:
loewis, georg.brandl, nijel, pitrou, r.david.murray, neologix messages:
+ msg125368
|
2011-01-04 21:40:37 | r.david.murray | set | nosy:
+ r.david.murray messages:
+ msg125365
|
2011-01-04 21:08:33 | loewis | set | status: pending -> open nosy:
+ loewis messages:
+ msg125362
|
2011-01-04 14:13:16 | pitrou | set | status: open -> pending
messages:
+ msg125325 resolution: not a bug nosy:
georg.brandl, nijel, pitrou, neologix |
2011-01-04 14:11:32 | nijel | set | nosy:
georg.brandl, nijel, pitrou, neologix messages:
+ msg125324 |
2011-01-04 14:10:23 | neologix | set | nosy:
+ neologix messages:
+ msg125323
|
2011-01-04 14:06:34 | georg.brandl | set | nosy:
+ georg.brandl messages:
+ msg125322
|
2011-01-04 14:01:45 | pitrou | set | messages:
+ msg125321 |
2011-01-04 13:59:38 | nijel | set | messages:
+ msg125320 |
2011-01-04 13:49:42 | pitrou | set | versions:
+ Python 3.3, - Python 2.7 nosy:
+ pitrou
messages:
+ msg125318
type: behavior -> enhancement |
2011-01-04 13:42:42 | nijel | create | |