endgrent#
Close the group database after iterating it.
endgrent is the cleanup half of the group-database iteration trio
setgrent / getgrent / endgrent. It tells
the C library that you are done walking /etc/group (or the NSS
source behind it), releasing any file descriptors or cached state the
library opened on your behalf. After endgrent, the next
getgrent call starts a fresh iteration from the top.
Synopsis#
endgrent;
endgrent();
No arguments, no meaningful return value.
What you get back#
The return value is unspecified and must not be relied on. endgrent
is called for its side effect — closing the group database — not for a
result. Treat it as a void call.
endgrent; # correct
my $ok = endgrent; # wrong: $ok is not a success flag
If your platform does not implement endgrent, the call croaks with
The endgrent function is unimplemented at runtime. This is
effectively a compile-once check — if the function works on your
system at all, it will continue to.
Global state it touches#
endgrent operates purely on the libc-internal group-iteration state
that setgrent and getgrent share. It
reads and writes no Perl special variables. It does not alter
$!: a failure path that sets errno in the underlying
C call is not surfaced to Perl.
The iteration state is per-process, not per-thread. In a threaded
program, one thread’s endgrent closes the iteration for every thread
— see Edge cases.
Examples#
The canonical iterate-and-close pattern. Always pair a
setgrent / getgrent loop with endgrent
so long-running programs do not leak the file descriptor the C library
keeps open:
setgrent;
while (my @g = getgrent) {
my ($name, $passwd, $gid, $members) = @g;
print "$name ($gid): $members\n";
}
endgrent;
Dropping into endgrent mid-iteration is legal — it simply abandons
whatever cursor position the library was holding:
setgrent;
while (my @g = getgrent) {
last if $g[0] eq 'wheel'; # found what we wanted
}
endgrent; # release the handle anyway
Restarting iteration. endgrent followed by
setgrent is the portable way to rewind:
setgrent;
my @first_pass = collect_groups();
endgrent;
setgrent;
my @second_pass = collect_groups(); # starts over from the top
endgrent;
Defensive cleanup in a END block for programs that might die mid-walk:
setgrent;
END { endgrent }
while (my @g = getgrent) { ... } # any die still triggers END
Edge cases#
Calling
endgrentwithout a priorsetgrentorgetgrentis harmless. The C library silently does nothing if no iteration is in progress.Calling it twice in a row is also harmless — the second call is a no-op.
Parser ambiguity.
endgrenttakes no argument and has the precedence of a named unary operator. A bareword expression immediately to its right will be parsed as an argument and rejected:endgrent or die; # WRONG: parses as endgrent(or die) endgrent() or die; # right: empty parens disambiguate
In practice there is nothing to check the return value against, so this trap rarely bites — but the same rule applies to any chained expression.
Threads share the iteration.
endgrentfrom one thread ends iteration for all threads of the same process, because the underlying state is process-global. Do not interleavegetgrentcalls across threads expecting each to see every record.NSS and caching. On systems where the group database is served through NSS (nss_ldap, nss_sss, etc.),
endgrentreleases per-module caches that the NSS backend may hold. Long-lived daemons that walk the group database periodically should callendgrentafter each walk to avoid accumulating backend state.No effect on name-lookup calls.
getgrnamandgetgrgidare independent of the iteration cursor.endgrentdoes not invalidate their results or cached data, and you do not need to callendgrentbefore or after them.Unimplemented on some platforms. Perl croaks
The endgrent function is unimplementedif the host libc has noendgrent(3). All modern Linux, BSD, and macOS systems provide it.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
setgrent— open or rewind the group database before walking it; always the prologue to an iteration that ends withendgrentgetgrent— pull the next record from the iterationendgrentclosesgetgrnam— look up one group by name, independent of the iteration cursor; noendgrentneededendpwent— the parallel cleanup call for the passwd database; the two iterations are independent and both need closing if you opened both