From: nobuyoshi nakada Date: 2005-12-22T14:38:33+09:00 Subject: Re: getpasswd Hi, At Thu, 22 Dec 2005 09:00:56 +0900, Bertram Scharpf wrote in [ruby-core:06973]: > The reason is easy to find: the `static struct passwd' that > is used internally by both the `Etc::passwd' method and > `expand_path' substitute-~ mechanism. `Etc' even seems to > protect itself from using the struct twice using a static > variable named `passwd_blocking'. Hmmm, get{pw,gr}*_r() family aren't actually reentrant at all. Just a dirty hack. Otherwise, iterative methods in etc.c would have to read all items at first. Index: file.c =================================================================== RCS file: /cvs/ruby/src/ruby/file.c,v retrieving revision 1.233 diff -U2 -p -r1.233 file.c --- file.c 21 Dec 2005 09:20:00 -0000 1.233 +++ file.c 22 Dec 2005 05:32:09 -0000 @@ -92,4 +92,29 @@ be_fchown(int fd, uid_t owner, gid_t gro #endif /* __BEOS__ */ +#ifdef HAVE_PWD_H +int rb_passwd_blocking; + +struct passwd * +rb_getpwnam(const char *name) +{ + if (rb_passwd_blocking) { + rb_raise(rb_eRuntimeError, "parallel passwd iteration"); + } + return getpwnam(name); +} + +struct passwd * +rb_getpwuid(rb_uid_t uid) +{ + if (rb_passwd_blocking) { + rb_raise(rb_eRuntimeError, "parallel passwd iteration"); + } + return getpwuid(uid); +} + +#define getpwnam rb_getpwnam +#define getpwuid rb_getpwuid +#endif + VALUE rb_cFile; VALUE rb_mFileTest; Index: process.c =================================================================== RCS file: /cvs/ruby/src/ruby/process.c,v retrieving revision 1.142 diff -U2 -p -r1.142 process.c --- process.c 20 Nov 2005 03:30:43 -0000 1.142 +++ process.c 22 Dec 2005 05:32:05 -0000 @@ -117,4 +117,28 @@ static VALUE S_Tms; do {int saved_errno = errno; stmts; errno = saved_errno;} while (0) +#ifdef HAVE_GRP_H +int rb_group_blocking; + +struct group * +rb_getgrnam(const char *name) +{ + if (rb_group_blocking) { + rb_raise(rb_eRuntimeError, "parallel group iteration"); + } + return getgrnam(name); +} + +struct group * +rb_getgrgid(rb_gid_t gid) +{ + if (rb_group_blocking) { + rb_raise(rb_eRuntimeError, "parallel group iteration"); + } + return getgrgid(gid); +} + +#define getgrnam rb_getgrnam +#define getgrgid rb_getgrgid +#endif /* Index: ext/etc/etc.c =================================================================== RCS file: /cvs/ruby/src/ruby/ext/etc/etc.c,v retrieving revision 1.20 diff -U2 -p -r1.20 etc.c --- ext/etc/etc.c 12 Dec 2005 00:35:07 -0000 1.20 +++ ext/etc/etc.c 22 Dec 2005 05:08:56 -0000 @@ -108,4 +108,7 @@ setup_passwd(pwd) ); } + +RUBY_EXTERN int rb_passwd_blocking; +#define passwd_blocking rb_passwd_blocking #endif @@ -170,5 +173,4 @@ etc_getpwnam(obj, nam) #ifdef HAVE_GETPWENT -static int passwd_blocking = 0; static VALUE passwd_ensure() @@ -317,4 +319,7 @@ setup_group(grp) mem); } + +RUBY_EXTERN int rb_group_blocking; +#define group_blocking rb_group_blocking #endif @@ -375,5 +380,4 @@ etc_getgrnam(obj, nam) #ifdef HAVE_GETGRENT -static int group_blocking = 0; static VALUE group_ensure() -- Nobu Nakada