Open SteveLauC opened 2 years ago
I think it would be clearer if unsafe { endgrent() };
would be moved below the loop.
I think it would be clearer if
unsafe { endgrent() };
would be moved below the loop.
Good catch! It should be.
Hm. This would work. But I suggest changing the interface to avoid collecting into a Vec. More like this:
struct GroupIter {...}
impl Iterator for GroupIter {
type Item = Group;
fn iter(&mut self) -> Self::Item {..}
}
impl Group {
fn iter() -> GroupIter {...}
}
@asomers this could easily accidentially run into problems when multiple parts of the program access the thread-local iterator using multiple iterator instances. Why not use FromIterator
instead?
You could mark the GroupIter as !Send
and !Sync
to prevent multiple threads from accessing it. How do you suggest using FromIterator
?
Oh, not only that, I was talking about creating multiple instances of GroupIter
on the same thread, then accessing them in such a way that they all get consumed in a mixed fashion, so at least some of them get not iterated from front-to-back without interleaving with another one. This would afaik result in each of them "receiving" a partition of the entries, which imo is bad.
Well, that wouldn't happen if you use getgrent_r
, right?
We still use setgrent
and endgrent
, they don't take a buffer/context handle, so I assume they wouldn't be safe to use in that case, right?
Oh, not only that, I was talking about creating multiple instances of
GroupIter
on the same thread, then accessing them in such a way that they all get consumed in a mixed fashion, so at least some of them get not iterated from front-to-back without interleaving with another one. This would afaik result in each of them "receiving" a partition of the entries, which imo is bad.
This is correct, it is safe only if we can guarantee that there is only one instance running cause `setpwent/endpwment will modify a global state which makes instances collide with each other.
rust-users
is a crate that does a similar job. They expose these syscalls in an interface of an iterator, but they mark this as unsafe, here is the document.
pub unsafe fn all_users() -> impl Iterator<Item = User>
And here is a related issue.
BTW, in this perspective, my draft impl is also unsafe if multiple functions are run in parallel, right?
BTW, in this perspective, my draft impl is also unsafe if multiple functions are run in parallel, right?
yes. Unless you protect the code section between setgrent
and endgrent
(inclusive these calls) and such with a Mutex.
These two syscalls sequentially scan the
/etc/passwd/ and
/etc/group` databases and return all the entries in those files one by one.Signature
Implementation
On some OSes, we have non-reentrant functions
getpwent_r()
andgetgrent_r()
. If so, they will be used. Otherwise, will usegetpwent()
andgetgrent()
.Here is draft implementation of
getgrent
under Linux:Note
setgrent
andendgrent
inside, which actually changes the semantics of this syscall.Due to Note
1
, perhaps we can give a better name to those syscalls, like: