classification
Title: posix.getgroups() failure on Mac OS X
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: ronaldoussoren Nosy List: belopolsky, flox, ixokai, l0nwlf, loewis, ned.deily, orsenthil, pitrou, r.david.murray, ronaldoussoren
Priority: normal Keywords: patch

Created on 2010-02-10 15:04 by michael.foord, last changed 2011-03-14 20:06 by ronaldoussoren. This issue is now closed.

Files
File name Uploaded Description Edit
issue7900.diff Alexander.Belopolsky, 2010-02-20 20:21
tg.py Alexander.Belopolsky, 2010-02-22 15:57
apple-2.5-fix-posixmodule.c.diff Alexander.Belopolsky, 2010-02-22 16:27
apple-2.6-fix-posixmodule.c.diff Alexander.Belopolsky, 2010-02-22 16:28
no-darwin-ext.diff Alexander.Belopolsky, 2010-02-22 22:50 Undefine _DARWIN_C_SOURCE in posixmodule
issue7900-tests.diff Alexander.Belopolsky, 2010-02-23 02:51 additional tests
os-getgroups.patch ronaldoussoren, 2010-02-23 08:29
issue7900-1.diff Alexander.Belopolsky, 2010-02-23 13:18
getsetgroups-bug.tar ronaldoussoren, 2010-02-23 22:23
os-getgroups-v2.patch ronaldoussoren, 2010-05-05 14:42
os-getgroups-v3.patch ronaldoussoren, 2010-05-06 05:23
issue7900-trunk.diff belopolsky, 2010-06-23 00:19
smime.p7s ronaldoussoren, 2010-08-03 08:08
Messages (83)
msg99165 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-02-10 15:04
test_posix fails on trunk on Mac OS X (Snow Leopard)

test.test_support.TestFailed: Traceback (most recent call last):
  File "Lib/test/test_posix.py", line 42, in testNoArgFunctions
    posix_func()
OSError: [Errno 22] Invalid argument

Python 2.7a3+ (trunk:78129M, Feb 10 2010, 10:40:28) 
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin
>>> import posix
>>> posix.getgroups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
msg99274 - (view) Author: Shashwat Anand (l0nwlf) Date: 2010-02-12 17:30
I don't see any issue here, runs perfectly fine on Mac OS X (Snow Leopard)

Shashwat-Anands-MacBook-Pro:test l0nwlf$ pwd
/Users/l0nwlf/python-svn/Lib/test
Shashwat-Anands-MacBook-Pro:test l0nwlf$ python2.7 test_posix.py
testNoArgFunctions (__main__.PosixTester) ... ok
test_access (__main__.PosixTester) ... ok
test_chdir (__main__.PosixTester) ... ok
test_chflags (__main__.PosixTester) ... ok
test_chown (__main__.PosixTester) ... ok
test_confstr (__main__.PosixTester) ... ok
test_dup (__main__.PosixTester) ... ok
test_dup2 (__main__.PosixTester) ... ok
test_fchown (__main__.PosixTester) ... ok
test_fdopen (__main__.PosixTester) ... ok
test_fstat (__main__.PosixTester) ... ok
test_fstatvfs (__main__.PosixTester) ... ok
test_ftruncate (__main__.PosixTester) ... ok
test_getcwd_long_pathnames (__main__.PosixTester) ... ok
test_initgroups (__main__.PosixTester) ... ok
test_lchflags (__main__.PosixTester) ... ok
test_lchown (__main__.PosixTester) ... ok
test_lsdir (__main__.PosixTester) ... ok
test_osexlock (__main__.PosixTester) ... ok
test_osshlock (__main__.PosixTester) ... ok
test_pipe (__main__.PosixTester) ... ok
test_stat (__main__.PosixTester) ... ok
test_statvfs (__main__.PosixTester) ... ok
test_strerror (__main__.PosixTester) ... ok
test_tempnam (__main__.PosixTester) ... ok
test_tmpfile (__main__.PosixTester) ... ok
test_umask (__main__.PosixTester) ... ok
test_utime (__main__.PosixTester) ... ok

----------------------------------------------------------------------
Ran 28 tests in 0.025s

OK

Shashwat-Anands-MacBook-Pro:test l0nwlf$ python2.7 --versionPython 2.7a3+
Shashwat-Anands-MacBook-Pro:test l0nwlf$ python2.7 
Python 2.7a3+ (trunk:78165, Feb 12 2010, 22:36:03) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import posix
>>> posix.getgroups()
[20, 204, 100, 98, 81, 80, 79, 61, 12, 402, 401]
>>>
msg99277 - (view) Author: Senthil Kumaran (orsenthil) * (Python committer) Date: 2010-02-12 18:03
What is the (Apple Inc. build 5646) (dot 1) vs normal (Apple Inc. build 5646). ?

While, ronald.oussoren did make a lot some changes recently (r78149 to r78152).This fix could have been a side-effect of one of it, thought I could not find the direct correlation.
msg99279 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-02-12 18:29
I still see it on trunk (revision 78165). No idea what the (dot 1) means.
msg99304 - (view) Author: Shashwat Anand (l0nwlf) Date: 2010-02-13 03:26
It seems they are basically the same thing, the version of GCC and the build of OS X(latest in the case here). Was not able to figure out the (dot 1) stuff though.
msg99306 - (view) Author: Senthil Kumaran (orsenthil) * (Python committer) Date: 2010-02-13 03:54
please not remove the nosy list. ( I guess, you did it by accident).
let's wait for ronald's response.
msg99307 - (view) Author: Shashwat Anand (l0nwlf) Date: 2010-02-13 04:30
Thanks for correcting it back. I did not even realized it.
msg99310 - (view) Author: Shashwat Anand (l0nwlf) Date: 2010-02-13 07:22
5646 and 5646.1 are the builds of GCC by Apple. The various builds of gcc are present on http://www.opensource.apple.com/source/gcc/ 

[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin -> http://www.opensource.apple.com/source/gcc/gcc-5646.1/

[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
 -> http://www.opensource.apple.com/source/gcc/gcc-5646/
msg99390 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-16 09:08
Michael: 
* which configure options do you use?
* which xcode version do you use? 
  (this shouldn't be relevant, I'm interested in what causes the dot 1
  suffix)
* If you use --enable-universalsdk: do you have the 10.4 SDK installed
  (should be installed in "$(xcode-select -print-path)/SDKs/")

I cannot reproduce this with r78205, OSX 10.6.2/10C540, gcc version 4.2.1 (Apple Inc. build 5659), Xcode 3.2.2/10M2135.
msg99391 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-16 09:12
A related question: is this issue present in the 3.x trunk?

(BTW: feel free to assign all OSX related issues to me)
msg99556 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-02-19 05:06
I'm not seeing the same issue on my Macbook Pro. I can get all this info from my desktop machine (Mac Pro) when I return from PyCon.
msg99625 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-20 18:37
Michael,

Can you post the output of "groups" and "id" command from your Mac?  It looks like posix_getgroups cannot handle more than NGROUPS_MAX groups and NGROUPS_MAX is 16 on Mac OS.
msg99627 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-20 19:13
I was able to reproduce the error.  First, add your user name to multiple test groups as follows:

$ sudo dscl . -create /Groups/testN GroupMembership username
(repeat 16 times with different Ns)

$ ./python.exe 
Python 2.7a3+ (trunk:78265M, Feb 20 2010, 13:18:22) 
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import posix
>>> posix.getgroups()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
msg99628 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-20 20:14
I am submitting a fix.  I am using the following feature documented in getgroups(2):
"""
If _DARWIN_C_SOURCE is defined, getgroups() can return more than {NGROUPS_MAX} groups.
"""

It appears that _DARWIN_C_SOURCE is defined in the standard python configuration on Mac OS X.  Tested on 10.6 only.
msg99630 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-20 20:43
It looks like the current implementation is not POSIX compliant because it assumes that NGROUPS_MAX is compile time constant.  However, according to <http://www.opengroup.org/onlinepubs/000095399/functions/getgroups.html>, "Application writers should note that {NGROUPS_MAX} is not necessarily a constant on all implementations."

I would suggest using my _DARWIN_C_SOURCE implementation unconditionally and make similar changes to posix_setgroups, but this is probably a subject for a separate issue.
msg99631 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-20 20:43
It looks like the current implementation is not POSIX compliant because it assumes that NGROUPS_MAX is compile time constant.  However, according to <http://www.opengroup.org/onlinepubs/000095399/functions/getgroups.html>, "Application writers should note that {NGROUPS_MAX} is not necessarily a constant on all implementations."

I would suggest using my _DARWIN_C_SOURCE implementation unconditionally and make similar changes to posix_setgroups, but this is probably a subject for a separate issue.
msg99675 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-02-21 18:58
> I would suggest using my _DARWIN_C_SOURCE implementation
> unconditionally and make similar changes to posix_setgroups, but this
> is probably a subject for a separate issue.

I would propose a different strategy: if _SC_NGROUPS_MAX is defined, use
that to find out how much memory to allocate, otherwise, fall back to
the current max array size. Can you find out whether doing so would also
fix the issue at hand?
msg99693 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-21 22:29
On Sun, Feb 21, 2010 at 1:58 PM, Martin v. Löwis <report@bugs.python.org> wrote:
..
> I would propose a different strategy: if _SC_NGROUPS_MAX is defined, use
> that to find out how much memory to allocate, otherwise, fall back to
> the current max array size. Can you find out whether doing so would also
> fix the issue at hand?

I am afraid that the following is the evidence that it won't:

Python 2.7a3+ (trunk:78265M, Feb 20 2010, 15:20:36)
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.sysconf('SC_NGROUPS_MAX')
16
>>> len(os.getgroups())  # with the patch
22
msg99759 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-22 15:57
Here is another interesting fact: Mac OS 10.6 comes with python 2.5 and 2.6 preinstalled:

$ python2.5 -V
Python 2.5.3c1
$ python2.6 -V
Python 2.6.1

Neither of these exhibit the same bug, but both are broken in some way.  Given

$ cat tg.py
import os
g = os.getgroups()
print g
os.setgroups(g[:5])
print os.getgroups()

$ sudo python2.5 tg.py
[0, 101, 204, 100, 98, 80, 61, 29, 20, 12, 9, 8, 5, 4, 3, 2]
[0, 101, 204, 100, 98]
$ sudo python2.6 tg.py
[0, 101, 204, 100, 98, 80, 61, 29, 20, 12, 9, 8, 5, 4, 3, 2, 1, 401]
[0, 101, 204, 100, 98, 80, 61, 29, 20, 12, 9, 8, 5, 4, 3, 2, 1, 401]

Note that python2.5 truncates the group list which is 
$ sudo id -G
0 101 204 100 98 80 61 29 20 12 9 8 5 4 3 2 1 401

but setgroups works as expected.  In contrast, python2.6 reports all groups correctly, but setgroups has no effect.
msg99766 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-22 16:05
Apparently, Apple patches posix_[gs]etgroups functions as follows:

for 2.5: http://www.opensource.apple.com/source/python/python-44/2.5/fix/posixmodule.c.ed

for 2.6: http://www.opensource.apple.com/source/python/python-44/2.6/fix/posixmodule.c.ed
msg99772 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-22 16:17
And as usual they can't be bothered to describe what the patch does, or even use regular universal diffs.
msg99775 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-22 16:27
I've converted apple patches to unified diffs, but I cannot reproduce 2.5 behavior.
msg99862 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-22 22:50
After some head-scratching, I figured out how to reproduce stock python2.5 behavior.  It turns out that defining _DARWIN_C_SOURCE not only allows getgroups() output to exceed NGROUPS_MAX (as documented), but also effectively disables setgroups() which is not documented.

With no-darwin-ext.diff patch and previously attached tg.py, I see

$ cat tg.py
import os
g = os.getgroups()
print(g)
os.setgroups(g[:5])
print(os.getgroups())

$ sudo ./python.exe tg.py
[0, 101, 204, 100, 98, 80, 61, 29, 20, 12, 9, 8, 5, 4, 3, 2]
[0, 101, 204, 100, 98]

which is the same as with stock python2.5:

$ sudo python2.5 tg.py
[0, 101, 204, 100, 98, 80, 61, 29, 20, 12, 9, 8, 5, 4, 3, 2]
[0, 101, 204, 100, 98]

Note that root is a member of 18 groups on my system, but the last two are truncated by os.getgroups().

It is tempting to adopt no-darwin-ext.diff as a solution to this issue because allowing more than NGROUPS_MAX (or sysconf(_SC_NGROUPS_MAX) which should be the same) groups is really a Mac OS bug.

In order to have both working os.setgroups() and os.getgroups() supporting more than NGROUPS_MAX results, it appears that the two functions should be compiled in separate compilation units which is probably too big of a price to pay for the functionality.

Also, my issue7900.diff, while likely to work in most practical situation is vulnerable to a race condition if group membership is expanded between two calls to getgroups.
msg99865 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-22 23:08
I am reclassifying this as a crash because os.getgroups() crashes the interpreter when python is running as root on an unmodified system:

$ sudo ./python.exe  -c "import os; os.getgroups()"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
OSError: [Errno 22] Invalid argument

This is also a regression apparently introduced in r63955.
msg99901 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 07:20
Alexander:  What makes you think r63955 introduced the problem? 
 
Btw. This does not crash the interpreter: the example you give causes an exception and cleanly shuts down the interpreter. The exception is unwanted, but I wouldn't call it a crash.

The Apple fix for getgroups in python2.6 is odd, it uses an undocumented API (getgrouplist_2).

If I read the manpage correctly there is a posixly correct way to implement os.getgroups:

* call getgroups(MAX_GROUPS,...)
* if that fails: call getgroups(0,...), the result is groupcount
* allocate an array of groupcount gid_t's and call getgroups(groupcount)

I'll work on a patch that implements this.
msg99903 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 08:29
On my system with the attached patch (os-getgroups.patch):

$ sudo ./python.exe
Python 2.7a3+ (trunk:78371M, Feb 23 2010, 09:19:44) 
[GCC 4.2.1 (Apple Inc. build 5659)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getgroups()
[11, 0, 11, 0, 3, 61, 29, 20, 3511889, 1, 3368710, 1, 2, 0, 1537888, 1, 223]
>>> len(_)
17
>>> 


I haven't tested yet if this version works on other platforms, but at least on Linux and HP-UX the manpage is similar enough to the one on OSX that I expect it to work there as well. (All 3 manpage say that getroups(0, grouplist) returns the number of secondary groups without modifying the grouplist argument).


BTW. os.setgroups also needs fixing for OSX: as it is a python script cannot set the grouplist to a value with more than 16 entries, even though the system is obviously capable of doing just that.

BTW2. The patch is for the trunk.
msg99908 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 13:18
On Tue, Feb 23, 2010 at 2:20 AM, Ronald Oussoren <report@bugs.python.org> wrote:
> ..
> Alexander:  What makes you think r63955 introduced the problem?

That revision introduced _DARWIN_C_SOURCE which, as I explained, has
two effects on get/setgroups:

"""
It turns out that defining _DARWIN_C_SOURCE not only allows
getgroups() output to exceed NGROUPS_MAX (as documented), but also
effectively disables setgroups() which is not documented.
"""

I further added:

"""
In order to have both working os.setgroups() and os.getgroups()
supporting more than NGROUPS_MAX results, it appears that the two
functions should be compiled in separate compilation units which is
probably too big of a price to pay for the functionality.
"""

I agree that this is a important distinction, but I seem to recall
discussion on python-dev or elsewhere on the tracker that concluded
that unexpected exceptions can be classified as crashes.  For most
users the difference between hard and soft crash is purely academic -
in either case their python program terminates due to a bug in python
and the "type" menu does not have separate entries for hard and soft
crashes.

> The Apple fix for getgroups in python2.6 is odd, it uses an undocumented API
> (getgrouplist_2).

I agree, Apple patch is not acceptable.  Not only it is undocumented,
but I suspect it is simply wrong because getgrouplist_2 is likely to
be a variant of getgrouplist that handles memory allocation and
returns group list from system's group database rather than from
per-process setting. (I have not verified that point, though.)

>
> If I read the manpage correctly there is a posixly correct way to implement os.getgroups:
>
> * call getgroups(MAX_GROUPS,...)

Note that MAX_GROUPS is 65536 on Linux and may be even higher on other
systems.  Allocating 256K on heap is wasteful and allocating the same
on the stack may even hard crash python.

> * if that fails: call getgroups(0,...), the result is groupcount

Please note the following comment I found in GNU coreutils source code:

/* On at least Ultrix 4.3 and NextStep 3.2, getgroups (0, NULL) always
   fails.  On other systems, it returns the number of supplemental
   groups for the process.  This function handles that special case
   and lets the system-provided function handle all others.  However,
   it can fail with ENOMEM if memory is tight.  It is unspecified
   whether the effective group id is included in the list.  */

This is more or less what my original patch did, but it suffers from a
race condition.

I am attaching a patch that I wrote yesterday, but did not submit
because it does not fix setgroups.  I am attaching it now so that we
can compare our approaches.
msg99909 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 13:28
Ronald,

Have you tested your patch with issue7900-tests.diff?  

On my system:

$ ./python.exe Lib/test/test_posix.py
testNoArgFunctions (__main__.PosixTester) ... Segmentation fault

and

$ sudo ./python.exe Lib/test/test_posix.py
..
FAIL: test_setgroups (__main__.PosixGroupsTester)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Lib/test/test_posix.py", line 403, in test_setgroups
    self.assertListEqual(groups, posix.getgroups())
AssertionError: Lists differ: [0] != [3419130827, 3419130827, 34191...

First differing element 0:
0
3419130827

Second list contains 17 additional elements.
First extra element 1:
3419130827

- [0]
+ [3419130827,
+  3419130827,
+  3419130827,
+  3419130827,
+  4227582923,
+  4227595259,
+  64507,
+  16777216,
+  3688580934,
+  3688618971,
+  4867048,
+  1,
+  3688618971,
+  3688618971,
+  3688618971,
+  3688618971,
+  3688618971,
+  3688618971]
..
msg99910 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-02-23 13:42
'crash' has, as far as I know, always been only for interpreter crashes (segfaults).  These are what we refer to as 'crashers'.
msg99913 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 13:46
My patch is very lightly tested and I didn't try to use the additional testcases. 

I get test failures, but no crashes, when I do run the additional tests. I haven't had time to review the testcases though. 

What I did notice though is that the tests don't actually test the issue at hand: having more than 16 secondairy groups on OSX.

I'm not too thrilled about your approach of growing the grouplist argument of getgroups until the results fit, the comment in the coreutils sources refers to two very old unix flavors and IMHO it is not worthwhile to try to support those.

Wrt. the value of MAX_GROUPS on Linux: we could change the test that defined MAX_GROUPS to ensure that the value doesn't get too large, from:

#ifdef NGROUPS_MAX


to:

#if defined(NGROUPS_MAX) && NGROUPS_MAX <= 64

This combined with my patch would result in less stack usage while still working when a user has a lot of secondary groups.


I agree that Apple's patch is broken, it almost certainly reads the secondary groups from the user database instead of returning the actual value for the running process (based on the prototype and additional includes).
msg99919 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 14:42
On Tue, Feb 23, 2010 at 8:46 AM, Ronald Oussoren <report@bugs.python.org> wrote:
..
> What I did notice though is that the tests don't actually test the issue at hand:
> having more than 16 secondairy groups on OSX.

This is easy to fix: just add another entry in groups

+    def test_setgroups(self):
+        for groups in [[0], range(16)]:

I did not do it for two reasons:

1. Laziness. :-)  It was easier for me to just replace "16" above with
other values in my tests than to introduce platform checks.  I believe
16 groups is supported on all relevant platforms.

2. I am not sure python should support non-posix behavior and allow
more than os.sysconf('SC_NGROUPS_MAX') groups to be returned from
os.getgroups().  IMO, users who need more than 16 groups on OSX should
bug Apple to fix sysconf(_SC_NGROUPS_MAX).
msg99926 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 15:24
On Tue, Feb 23, 2010 at 8:46 AM, Ronald Oussoren <report@bugs.python.org> wrote:
> ..
> I get test failures, but no crashes, when I do run the additional tests.

The crash that I see is apparently due to underallocated  memory:

 alt_grouplist = PyMem_Malloc(n);

should be

 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));

..
> I'm not too thrilled about your approach of growing the grouplist argument of
> getgroups until the results fit, the comment in the coreutils sources refers to two > very old unix flavors and IMHO it is not worthwhile to try to support those.
>

You are probably right on this point, but the main issue with using
getgroups(0, ..) is the race condition that it introduces.  If another
thread adds a group between n = getgroups(0, ..) and getgroups(n, ..)
calls, the second call will fail.

Makes sense regardless of the approach.
msg99928 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 15:33
E-mail to tracker handling still seems to remove '>' quoted lines.   I am reposting a couple of comments that got clobbered:

--
> * allocate an array of groupcount gid_t's and call getgroups(groupcount)
>
This is more or less what my original patch did, but it suffers from a
race condition.

> I'll work on a patch that implements this.
>
I am attaching a patch that I wrote yesterday, but did not submit
because it does not fix setgroups.  I am attaching it now so that we
can compare our approaches.

--


> Wrt. the value of MAX_GROUPS on Linux: we could change the test that defined > MAX_GROUPS to ensure that the value doesn't get too large, from:
>
> #ifdef NGROUPS_MAX
>
>
> to:
>
> #if defined(NGROUPS_MAX) && NGROUPS_MAX <= 64
>
> This combined with my patch would result in less stack usage while still working > when a user has a lot of secondary groups.
>
Makes sense regardless of the approach.
msg99933 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 17:01
I think I finally understand what is going on and ready to make what I believe is a reasonable proposal.

Setting _DARWIN_C_SOURCE (or _DARWIN_UNLIMITED_GETGROUPS) replaces getgroups with a Darwin extension, but does not change setgroups:

$ nm tg1 | grep etgroups
                 U _getgroups
                 U _setgroups
$ nm tg2 | grep etgroups
                 U _getgroups$DARWIN_EXTSN
                 U _setgroups

(here tg2 is compiled with -D_DARWIN_C_SOURCE=1)

The extended getgroups$DARWIN_EXTSN is not getgroups at all and instead is effectively a call to getgrouplist(getpwuid(..)->pw_name, ..).  In other words, it reads the system database instead of the per-process list. (This also explains the choice made in Apple patch.)

This means that _DARWIN_C_SOURCE is not appropriate for posixmodule.c.

My recommendation is now to close this bug by reverting _DARWIN_C_SOURCE setting locally in posixmodule.c or globally in pyconfig.h in favor of more targeted settings in the modules that need Darwin extensions.

This will leave a feature request to add os.getgrouplist() for users who actually want to read the system database instead of per-process group list.

The other ideas related to allocation of grouplist buffer can be left as a "resource usage" issue.

Lack of support for more than 16 groups in OSX get/setgroups() should be left for Apple to take care of.  This limitation can be documented possibly as a conditional appendix to get/setgroups() docstrings.
msg99935 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 17:16
I'm -1 w.r.t changing the definition of _DARWIN_C_SOURCE, at least not without a thorough investigation on what else this changes. Removing _DARWIN_C_SOURCE without setting some other defines may well cause in removal of functions from header files (I'm  pretty sure that setting _POSIX_C_SOURCE without setting other defines removes anything that isn't posix from view).

How did you detect that the modern getgroups implementation doesn't query the kernel? That would be very odd.
msg99939 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 17:32
I'm probably being extremely dense at the moment, but the program below doesn't behave as I'd expect on OSX:

#include <unistd.h>

int main(void)
{
#if 1
	gid_t gids[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
	int r;
	r = setgroups(16, gids);
	if (r == -1) {
		perror("setgroups");
		return 1;
	}
#endif
	setgid(3);
	setuid(502);
	execl("/usr/bin/id", "/usr/bin/id", NULL);
	perror("exec");
	return 1;
}


I'd expect it to print something simular to this (when started as root, either through sudo or by logging in as root):

uid=502 gid=3(sys) groups=1(bin),2(daemon),3(sys),4,5(tty),6(disk),7(lp),8(www),9(kmem),10(wheel),11,12(mail),13(news),14(uucp),15(shadow),16(dialout)

That doesn't happen however, the output above is from a linux system. On OSX it prints the group information that's associated with the 502 account in the user database, and only prints the expected values when I call setuid(600), which is a UID that isn't in use on my system.

This is both with and without setting _DARWIN_C_SOURCE and even when compiling with deployment target 10.4 and using the 10.4 SDK.

I'm therefore in favor of keeping _DARWIN_C_SOURCE and adding the workaround for a larger number of groups as implemented in os-getgroups.patch.

This means that using
msg99941 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 17:47
On Tue, Feb 23, 2010 at 12:16 PM, Ronald Oussoren <report@bugs.python.org> wrote:
..
> How did you detect that the modern getgroups implementation doesn't
> query the kernel? That would be very odd.

I wish I could say that I mastered dtrace under OSX, but I am not there yet. :-)  There are two facts that convinced me that this is the case

1. Since setgroups is the same regardless of _DARWIN_C_SOURCE but getgroups returns different values after setgroups in programs compiled with an without _DARWIN_C_SOURCE, the problem must be in getgroups.

2. Setting breakpoint at getpwuid in gdb I see that it is not called when _DARWIN_C_SOURCE is not set, but when it is

(gdb) where
#0  0x00007fff86d2c487 in getpwuid ()
#1  0x00007fff86da229b in getgroups$DARWIN_EXTSN ()
#2  0x0000000100000ddd in printgroups ()
#3  0x0000000100000e6e in main ()
msg99944 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-23 18:55
David,

Can you unset "normal" priority from this issue.  Regardless of whether it is a crash or not a crash, this is a regression for which there is no user work-around.  It looks like "normal" priority makes the issue disappear from the top of "Show Open" search and this is inconvenient while the issue is being worked on.

On Tue, Feb 23, 2010 at 12:32 PM, Ronald Oussoren <report@bugs.python.org> wrote:
..
>        setgid(3);
>        setuid(502);
>        execl("/usr/bin/id", "/usr/bin/id", NULL);
..
> On OSX it prints the group information that's associated with the 502 > account in the user database, and only prints the expected values when > I call setuid(600), which is a UID that isn't in use on my system.
>

This looks like a bug (surprise!) in OSX' /usr/bin/id.  With a freshly compiled coreutils-8.4, your program behaves as you expect when using /usr/local/bin/id.
  

> This is both with and without setting _DARWIN_C_SOURCE and even when
> compiling with deployment target 10.4 and using the 10.4 SDK.

This is to be expected because your program only calls setgroups which is unaffected by _DARWIN_C_SOURCE settings.  Note that it will also fail regardless of compilation mode if you change 16 to 17.

> I'm therefore in favor of keeping _DARWIN_C_SOURCE and adding the
> workaround for a larger number of groups as implemented in
> os-getgroups.patch.

I don't understand the "therefore" part.  As you say, _DARWIN_C_SOURCE setting has no effect on your program, so what is the advantage of keeping it is posixmodule.c?

As I explained, with _DARWIN_C_SOURCE set,

"""
[OSX getgroups] is not getgroups at all and instead is effectively a call to getgrouplist(getpwuid(..)->pw_name, ..).  In other words, it reads the system database instead of the per-process list.
"""

Why do you think this is what users expect to get when calling posix.getgroups()?


> This means that using

It looks like the rest of your message was lost ...
msg99962 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 22:23
I've filed issue #7681618 in Apple's bugtracker with the attached file "getsetgroups-bug.tar" as a way to reproduce the issue.

I want to wait a little to see how Apple responds (although I don't expect a quick response).
msg99964 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-02-23 22:42
quoting compat(5) on OSX 10.6.2:

<quote>
     Defining _POSIX_C_SOURCE or _DARWIN_C_SOURCE causes library and kernel calls to conform to the SUSv3
     standards even if doing so would alter the behavior of functions used in 10.3.  Defining
     _POSIX_C_SOURCE also removes functions, types, and other interfaces that are not part of SUSv3 from the
     normal C namespace, unless _DARWIN_C_SOURCE is also defined (i.e., _DARWIN_C_SOURCE is _POSIX_C_SOURCE
     with non-POSIX extensions).  In any of these cases, the _DARWIN_FEATURE_UNIX_CONFORMANCE feature macro
     will be defined to the SUS conformance level (it is undefined otherwise).

     Starting in Mac OS X 10.5, if none of the macros _NONSTD_SOURCE, _POSIX_C_SOURCE or _DARWIN_C_SOURCE
     are defined, and the environment variable MACOSX_DEPLOYMENT_TARGET is either undefined or set to 10.5
     or greater (or equivalently, the gcc(1) option -mmacosx-version-min is either not specified or set to
     10.5 or greater), then UNIX conformance will be on by default, and non-POSIX extensions will also be
     available (this is the equivalent of defining _DARWIN_C_SOURCE).  For version values less that 10.5,
     UNIX conformance will be off (the equivalent of defining _NONSTD_SOURCE).
</quote>

If I read this correctly, this means that for deployment target 10.5 or later you must define _POSIX_C_SOURCE to get the correct version of getgroups, but that also hides all non-posix symbols in system headers. 

I haven't tested yet what the behavior is when neither _POSIX_C_SOURCE nor _DARWIN_C_SOURCE are defined (on OSX 10.4, 10.5 and 10.6).

BTW. It is possible to work around this by symbol renaming similarly to what Apple does in their headers to get the two variants of getgroups in the first place. But let's not go there unless there really is no other way.

As to your question "Why do you think this is what users expect to get when calling posix.getgroups()?": I'd expect that os.getgroups works just like it does in C code, and agrees with id(1). But then I'd also expect that os.setgroups affects the result of os.getgroups... Lame platform bugs are no fun :-(
msg100055 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-02-24 17:44
I still think that the sysconf version should be the correct one. If OSX fails to work correctly under that version, and causes Python to raise an exception - then that's a platform bug, and should only accept minimal work arounds.

So I propose to close this as "won't fix". Or, the original issue could be resolved by accepting EINVAL on OSX as a correct result of getgroups in the test suite.
msg100058 - (view) Author: Alexander Belopolsky (Alexander.Belopolsky) Date: 2010-02-24 18:02
On Wed, Feb 24, 2010 at 12:45 PM, Martin v. Löwis
<report@bugs.python.org> wrote:
..
> I still think that the sysconf version should be the correct one. If OSX fails to work correctly under
> that version, and causes Python to raise an exception - then that's a platform bug, and should only > accept minimal work arounds.
>

It is more than an exception.  In python 2.6+, os.getgroups() returns
wrong results.  It always reads system database instead of returning
the values that are set with os.setgroups().

> So I propose to close this as "won't fix". Or, the original issue could be resolved by accepting
> EINVAL on OSX as a correct result of getgroups in the test suite.
>

Supporting more than 16 groups is less important (and impossible
without a platform fix) than to have working get/setgroups for
reasonable number of groups.  This is how python behaved before
r63955.

At the very least unit tests that I submitted could be accepted
possibly with a skip on OSX if fixing the bug is not an option.
msg101850 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-03-28 00:51
I have a consistently failing test on my machine. If the answer is indeed "won't fix" and both os.getgroups() and os.setgroups() are not expected to work correctly on Mac OS X then the tests should be disabled for that platform.
msg105042 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-05-05 14:42
I agree with Michael that something should be done.

I propose to add commit os-getgroups-v2.patch, which is the almost same as os-getgroups.patch that I posted earlier, but adds a check for large values of NGROUPS_MAX (see msg99913 for the rationale)

This ensures that os.getgroups() will return a value that is consistent with the id(1) command on OSX and solves the original issue.

Sadly enough this won't fix the other issue that's mentioned in msg99759, because that is a platform issue.  In the current release of OSX it is impossible to both have os.getgroups that reflects calls to os.setgroups and os.getgroups that returns the same information as system tools, and therefore it is my opinion that we should keep the current behavior where we're at least consistent with system tools.
msg105065 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-05-05 18:22
The latest patch, os-getgroups-v2.patch, seems to have the same bug as I reported in msg99926:

"""
The crash that I see is apparently due to underallocated  memory:

 alt_grouplist = PyMem_Malloc(n);

should be

 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
"""

I no longer see the crash, but did not have a chance to investigate it further.  In any case, PyMem_Malloc(n) is clearly wrong and should be replaced by PyMem_Malloc(n * sizeof(gid_t)) or maybe better by PyMem_New(gid_t, n).

There are no tests in the patch and issue7900-tests.diff tests return "FAILED (failures=3, errors=2)" when ran as a superuser.
msg105067 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-05-05 18:41
Ronald> How did you detect that the modern getgroups implementation
Ronald> doesn't query the kernel? That would be very odd.

I have just found the source code for getgroups:

http://www.opensource.apple.com/source/Libc/Libc-594.1.4/sys/getgroups.c

As I suspected, it simply calls getgrouplist with the current user name.

From getgrouplist(3) manpage:

"""
The getgrouplist() function reads through the group file and calculates the group access list for the user specified in name. 
"""
msg105074 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-05-05 19:05
The PyMalloc error was a lame bug. I've also fixed another issue (missing parenthesis in an error return).

os-getgroups-v3.patch also adds unittests: 
* issue7900-tests.diff, but with all tests disabled on darwin (due to the broken implementation of getgroups) 
* a check that verifies that the result of os.getgroups is consistent with "id -G". This one is only tested on darwin because parsing the output of commands is fragile and I'm far from sure that the test will work on other platforms.
msg105086 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-05-05 20:39
Ronald,

Did you forget to attach your patch? I don't see v3.
msg108393 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-22 15:16
Ronald,

Please see my python-dev post in "red buildbots on 2.7" thread: 

http://mail.python.org/pipermail/python-dev/2010-June/100873.html

I argue that we should apply a fix along the lines of no-darwin-ext.diff while waiting for Apple to fix their bugs and support more than 16 groups in getgroups properly.

Your latest patch, while prevents getgroups from raising an exception, does not change the fact that getgroups return wrong values if group membership changes within the process.

Note that I propose to undefine _DARWIN_C_SOURCE for posixmodule.c only.  I think that is the right thing to do because defining _DARWIN_C_SOURCE is for invoking non-POSIX behavior.  If you still thing there may be other functions in posixmodule.c that require _DARWIN_C_SOURCE, we can probably find a way to change only getgroups, but I cannot figure out how to do it without adding extra source files.

For your reference, here is how getgroups is declared in unistd.h:


#if defined(_DARWIN_UNLIMITED_GETGROUPS) || defined(_DARWIN_C_SOURCE)
int      getgroups(int, gid_t []) __DARWIN_EXTSN(getgroups);
#else /* !_DARWIN_UNLIMITED_GETGROUPS && !_DARWIN_C_SOURCE */
int      getgroups(int, gid_t []);
#endif /* _DARWIN_UNLIMITED_GETGROUPS || _DARWIN_C_SOURCE */
msg108425 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-06-22 21:46
Here is a (untested) work-around that won't require undefining _DARWIN_C_SOURCE: After all includes, say

#ifdef __APPLE__
int	 posix_getgroups(int, gid_t []) __asm("_getgroups");
#define getgroups posix_getgroups
#endif

This should cause linking to the same symbol as without _DARWIN_UNLIMITED_GETGROUPS/_DARWIN_C_SOURCE
msg108430 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-23 00:19
Martin's solution works.  I don't think we need to worry about non-gcc compilers on OSX.  I am attaching a patch with tests where getgroups to id -G comparison test is skipped if id -G shows more than 16 groups.

Some of the added tests are skipped for non-privileged user.
msg108442 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-06-23 08:44
Wrt. non-gcc compilers: we do need to worry about those (there have been bugreports in the past about using the Intel compiler), but those compilers still have to be able to process system headers and Martin's patch basicly adds the definition from the system headers to posixmodule.c.

As mentioned on python-dev I'm still not happy about reverting to the previous behavior.
msg108456 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-23 15:39
Reposting from python-dev. See "os.getgroups() on MacOS X" <http://mail.python.org/pipermail/python-dev/2010-June/100960.html>.

"""
On Wed, Jun 23, 2010 at 2:08 AM, Ronald Oussoren <ronaldoussoren@mac.com> wrote:
..
>>
>>> * [Ronald's proposal] results in posix.getgroups not reflecting results of posix.setgroups
>>>
>>
>> This effectively substitutes getgrouplist called on the current user
>> for getgroups.  In 3.x, I believe the correct action will be to
>> provide direct access to getgrouplist which is while not POSIX (yet?),
>> is widely available.
>
> I don't mind adding getgrouplist, but that issue is seperator from this one. BTW. Appearently getgrouplist is posix
> (<http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/libc.html>), although this isn't a
> requirement for being added to the posix module.
>

(The link you provided leads to "Linux Standard Base Core
Specification," which is different from POSIX, but the distinction is
not relevant for our discussion.)

>
> It is still my opinion that the second option is preferable for better compatibility with system tools, even if the patch
> is more complicated and the library function we use can be considered to be broken.

Let me try to formulate what the disagreement is.  There are two
different group lists that can be associated with a running process:
1) The list of current supplementary group IDs maintained by the
system for each process and stored in per-process system tables; and
2) The list of the groups that include the uid under which the process
is running as a member.

The first list is returned by a system call getgroups and the second
can be obtained using system database access functions as follows:

pw = getpwuid(getuid())
getgrouplist(pw->pw_name, ..)

The first list can be modified by privileged processes using setgroups
system call, while the second changes when system databases change.

The problem that _DARWIN_C_SOURCE introduces is that it replaces
system getgroups with a database query effectively making the true
process' list of supplementary group IDs inaccessible to programs.
See source code at
<http://www.opensource.apple.com/source/Libc/Libc-594.1.4/sys/getgroups.c>.

The problem is complicated by the fact that OSX true getgroups call
appears to truncate the list of groups to NGROUPS_MAX=16.  Note,
however that it is not clear whether the system call truncates the
list or the underlying process tables are limited to 16 entries and
additional groups are ignored when the process is created.

In my view, getgroups and getgrouplist are two fundamentally different
operations and both should be provided by the os module.  Redefining
os.getgroups to invoke getgrouplist instead of system getgroups on one
particular platform to work around that platform's system call
limitation is not right.
"""
msg108482 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-06-23 19:41
I don't know how relevant this is to OS X, but on FreeBSD 6.3, kern.ngroups (maximum number of groups a uid may belong to) defaults to 16.
msg108483 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-06-23 20:07
> I don't know how relevant this is to OS X, but on FreeBSD 6.3,
> kern.ngroups (maximum number of groups a uid may belong to) defaults
> to 16.

It probably is: "sysctl kern.ngroups" also gives 16 on OSX 10.6.4
(Darwin 10.4.0).
msg109593 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-07-08 20:30
I got some time and did an experiment to deduce how multiple groups behave. This comment is rather long, a very short summary of the results is that OSX behaves oddly.

What I did:

* This is on OSX 10.6
* Create 18 groups named group1 to group18
* Create a user testuser that is a member of those groups:

$ id testuser
uid=504(testuser) gid=20(staff) groups=20(staff),514(group10),512(group8),513(group9),511(group7),515(group11),520(group16),516(group12),507(group3),517(group13),61(localaccounts),12(everyone),509(group5),505(group1),518(group14),510(group6),508(group4),521(group17),506(group2),402(com.apple.sharepoint.group.1),519(group15),522(group18)

  The user is actually a member of over 18 groups, it is a member of
  a number of system groups as well (but note: not the admin group)

* Create 18 files named 1 to 18, echo is owned by the group with
  the same number, contains its sequence number ('1' in 'group1')
  and has mode '0060':

$ ls -l
total 144
----rw----  1 ronald  group1   2 Jul  8 21:56 1
----rw----  1 ronald  group10  3 Jul  8 21:56 10
----rw----  1 ronald  group11  3 Jul  8 21:56 11
----rw----  1 ronald  group12  3 Jul  8 21:56 12
----rw----  1 ronald  group13  3 Jul  8 21:56 13
----rw----  1 ronald  group14  3 Jul  8 21:56 14
----rw----  1 ronald  group15  3 Jul  8 21:56 15
----rw----  1 ronald  group16  3 Jul  8 21:56 16
----rw----  1 ronald  group17  3 Jul  8 21:56 17
----rw----  1 ronald  group18  3 Jul  8 21:56 18
----rw----  1 ronald  group2   2 Jul  8 21:56 2
----rw----  1 ronald  group3   2 Jul  8 21:56 3
----rw----  1 ronald  group4   2 Jul  8 21:56 4
----rw----  1 ronald  group5   2 Jul  8 21:56 5
----rw----  1 ronald  group6   2 Jul  8 21:56 6
----rw----  1 ronald  group7   2 Jul  8 21:56 7
----rw----  1 ronald  group8   2 Jul  8 21:56 8
----rw----  1 ronald  group9   2 Jul  8 21:56 9


* Log in as that user, I used fast  user switching for that

* The user can read all files, that which means that the user is
  a member of all 18 groups as far as filesystem access is concerned

* My own account is not a member of the 18 groups and can not read
  the files (tested just in case access control is totally broken)

* Removing testuser from a group has no effect for running processes,
  but does affect new Terminal windows.

  This is different than what I had expected, I expected that the
  new window would have the same permissions as the already opened
  one.

* I also added a new group (group19) and made testuser a member of that
  group. Using the same technique as before I observed that a shell
  in a new Terminal window had group19 in its effective group list.


According to an engineer I had an e-mail conversation with this behaviour is intentional, which is why they patched /usr/bin/python in OSX 10.6 to use the new getgroups implementation.

IMO for most users the new getgroups (the one you get when _DARWIN_C_SOURCE is defined) more closely matches system behavior (that is, it returns the effective group list for regular processes). 

The only users that will see the odd behavior w.r.t. os.setgroups are those running scripts as root that use both os.setgroups and os.getgroups.  

Note that explicitly setting the effective uid and gid of processes is somewhat frowned upon by Apple, they'd prefer if all daemon processes where started using launchd and used launchd to start them using the correct permissions. A tool like ssh should use initgroup to initialize the effective group list, and that will do the right thing (which appearently is the odd behaviour I saw in new Terminal sessions).


I therefore propose to both keep _DARWIN_C_SOURCE and enhance the posix.getgroups implementation to deal with the fact that getgroups(3) may return more groups than we'd expect.


An earlier comment noted that such code might even be useful on Linux where MAX_GROUPS is 2**16 and the current implementation therefore uses a mostly unnecessarily large buffer on the stack, which may cause stack overflows.
msg109597 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-08 20:38
On Thu, Jul 8, 2010 at 4:30 PM, Ronald Oussoren <report@bugs.python.org> wrote:
..
> Note that explicitly setting the effective uid and gid of processes is somewhat frowned upon by Apple, they'd prefer if all daemon processes where started using launchd and used launchd to start them using the correct permissions. A tool like ssh should use initgroup to initialize the effective group list, and that will do the right thing (which appearently is the odd behaviour I saw in new Terminal sessions).

IIRC, the tests for initgroup in one of my patches also break with
_DARWIN_C_SOURCE on.
msg109599 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-07-08 20:52
Your test might expect different behaviour than what OSX actually does (this is an annoying limitation of unittests for wrappers of system behaviour, you'll implicitly test system behaviour as well as the wreappers themselves)

The behaviour w.r.t. secondairy groups is rather different than what I'd expect on a Unix system.
msg109607 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-08 21:18
This whole thing is a mess.  Great analysis, by the way.   I started a
similar experiment some time ago, but gave up when I discovered that a
member of the admin group can read any file regardless of permissions
settings.  Your solution is probably the best we can do for 2.7, but
for 3.x I still believe it is better to add os.getgrouplist and
document that on OSX users should use it in preference of
os.getgroups.  (A better explanation of the difference between the two
will probably be even better.)

On Thu, Jul 8, 2010 at 4:52 PM, Ronald Oussoren <report@bugs.python.org> wrote:
..
> The behaviour w.r.t. secondairy groups is rather different than what I'd expect on a Unix system.
msg109608 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-08 21:19
s/2.7/2.7.1/
msg111310 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-07-23 13:13
I've added issue9344 for adding os.getgroupslist. I'd prefer to keep adding that function separate from this issue. Btw. I'm +1 on adding such a function.

I will shortly commit a port of os-getgroups-v3.patch to 3.2, but without the tests in "PosixGroupsTester" because those explictly exclude OSX.
msg111353 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-07-23 16:08
Committed a port to python3 for os-getgroups-v3.patch in r83088,
including test cases (contrary to what I wrote before). 

Backports:
3.1: r83093

I'll backport to 2.7 and 2.6 tomorrow.


To complete the documentation for picking this patch: I've spoken with an Apple engineer about this issue. He says the the _DARWIN_C_SOURCE behavior is intentional and will not be reverted.  Apple's build of python, and other system tools (including perl) also use the _DARWIN_C_SOURCE behavior.
msg111441 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-07-24 10:06
2.7: r83124
2.6: r83126

The fix is now in all active branches, and I therefore close the issue.
msg112360 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-08-01 17:15
Reopening. This seems to have broken a couple of buildbots (two different issues):
http://www.python.org/dev/buildbot/builders/x86%20FreeBSD%202.7/builds/44/steps/test/logs/stdio
http://www.python.org/dev/buildbot/builders/sparc%20solaris10%20gcc%202.6/builds/737/steps/test/logs/stdio

If you want to have a global look at buildbot status, you can use bbreport:
http://code.google.com/p/bbreport/

Please don't commit platform-dependent code without at least watching the buildbots afterwards...
msg112365 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-08-01 18:48
The 2.6 problem (the solaris buildbot you link to) should be fixed in r83420.
msg112370 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-08-01 19:19
The other problem is fixed in r83431 for the py3k trunk.

I'll check the buildbot status tomorow morning, if that shows that the issue is truly gone I'll backport to the other branches and close this issue.
msg112563 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-08-03 08:08
Some else backported to 3.1 (that is, 3.1 already contained the fix when I tried the svnmerge)

Backported to 2.7 in r83643

Backported to 2.6 in r83650
msg120970 - (view) Author: Stephen Hansen (ixokai) Date: 2010-11-11 21:17
This test is failing again, and IIUC, largely due to the same sort of issues: http://www.python.org/dev/buildbot/all/builders/AMD64%20Leopard%203.1/builds/65

I was able to track down what exactly caused it to fail in this case on my box, though. Whatever "posix.getgroups()" ends up calling, appears to be tied to the current users login -- or at least, doesn't get updated when new groups are added to the user.

This failure happened because at some point after the buildbot was up and running, I added a new user to the machine (totally unconnected to the existing buildbot runner): this caused a new group to be added to the buildbot runner's user.

"id -G" starts returning that group immediately, but "posix.getgroups()" returns the same list as it had before. I was able to further reproduce it in Terminal, by having a console open, and compiling 3.1 there then adding a user, and running the test. It fails. Opening up a new terminal window, running the test-- and it succeeds. The original console continues to fail.
msg120974 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-11-11 22:03
This is the expected behavior on OSX. Apple has a pretty odd interpretation of the standards wrt getgroups and setgroups behavior. 

This behavior is not a bug in python

Sent from my iPhone

On 11 nov. 2010, at 22:17, Stephen Hansen <report@bugs.python.org> wrote:

> 
> Stephen Hansen <me+python@ixokai.io> added the comment:
> 
> This test is failing again, and IIUC, largely due to the same sort of issues: http://www.python.org/dev/buildbot/all/builders/AMD64%20Leopard%203.1/builds/65
> 
> I was able to track down what exactly caused it to fail in this case on my box, though. Whatever "posix.getgroups()" ends up calling, appears to be tied to the current users login -- or at least, doesn't get updated when new groups are added to the user.
> 
> This failure happened because at some point after the buildbot was up and running, I added a new user to the machine (totally unconnected to the existing buildbot runner): this caused a new group to be added to the buildbot runner's user.
> 
> "id -G" starts returning that group immediately, but "posix.getgroups()" returns the same list as it had before. I was able to further reproduce it in Terminal, by having a console open, and compiling 3.1 there then adding a user, and running the test. It fails. Opening up a new terminal window, running the test-- and it succeeds. The original console continues to fail.
> 
> ----------
> nosy: +ixokai
> versions: +Python 3.1, Python 3.2
> 
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue7900>
> _______________________________________
msg120975 - (view) Author: Stephen Hansen (ixokai) Date: 2010-11-11 22:09
Well, yes: the result of posix.getgroups is not a bug in Python, but is it a bug in the test? Should it be skipped on OSX, or some other solution?

Having buildbots fail because of something that's expected behavior is bad, isn't it?
msg120977 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-11-11 22:39
Right, regardless of whether or not it is a bug in python, IMO it *is* a bug in the python test suite, since we *expect* buildbots to be long running processes and therefore they are going to get hit by this failure on OSX periodically with a pretty high likelyhood.  Yes it is easily fixable (restart the builder), but it seems to me the test should be fixed somehow instead of putting that burden on the buildbot owner.

A skip on OSX would certainly be the simplest solution, and we could thereby indicate that we consider this behavior to be a bug in OSX.
msg121266 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-11-16 06:55
If anything should be done the test that checks the output of id -G should be removed if we want the buildbot to keep running without problems when you change the buildbots account.

After reading the message about the new failures again I don't think this is the OSX issue I mentioned (an which is explain in painfull detail earlier in the message list): it's just that the buildbot account got changed (unintentionally) while buildbot was running.

BTW. I don't understand why adding a new account to an OSX machine adds existing accounts to a new group, I have never seen that behaviour before (on OSX).

I'm -1 on changing anything for now and do not consider this to be a bug in Python or its testset.
msg121267 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-11-16 07:32
Ronald, on a normal unix system if you add a user to a group, any existing process/terminal session that runs 'id -G' will return the *old* group list.  Only a new process/terminal session will see the new group.

On OSX, 'id -G' returns the new group when run in an existing process/terminal session, according to what you wrote.

You can't just remove the 'id -G' from that test, because the test is using 'id -G' to get an independent verification of the list of group numbers as a check against what getgroups returns.  On a normal unix system, these two would match.  On OSX, they don't.

At the moment I don't see any alternative to skipping the test on OSX with a message that 'id -G' and 'getgroups' do not return the same group list on OSX.
msg121269 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-11-16 07:41
I'm still -1 on changing the test.  The test only fails when run from the buildbot and the buildbot account is changed without restarting buildbot. Changing the buildbot account should happen almost never, and IMO you should restart the buildbot daemon when you do so (and that's just good practice)

Disabling the test on OSX means that os.getgroups will not get tested at all on OSX, even when I run the testsuite from the command-line.
msg121270 - (view) Author: Stephen Hansen (ixokai) Date: 2010-11-16 07:52
The test is clearly verifying a *wrong* assumption: that id -G will match posix.getgroups() which simply does not hold on OSX.

I can reproduce this reliably on a completely clean, brand new installation of 10.5: from there the only things that have been done to the box is updating to 10.5.8, and then downloading the latest XCode tools that run on Leopard.

From here, launch Terminal: leave the console open. Run id -G; then run python and look at posix.getgroups().

Now, go into System Preferences and add a new user. Don't do anything else. Don't change anything with existing user. 

In the console that was already open, do id -G again. Now run python again, and do posix.getgroups() -- those no longer match.

Clearly IMHO the assumption that the test is declaring to be an expected result simply is not true in a OSX-Unix environment. 

Yes, if I go and *edit the actual slave user* then surely I can expect failures until I restarted the buildslave. But, if by merely adding a user causes a change to the buildslaves user by no action of my own, and that causes this test to be invalid... the test itself seems to be founded on assumptions which simply are not reliably true. 

I understand disabling the test means os.getgroups() will no longer be tested on OSX: and yet, the current situation is a specific behavior of os.getgroups() is tested which is *not* actually the guaranteed behavior of that operation. 

There is at least one very easy to reproduce situation in which id -G and posix.getgroups() do not match: I don't know if there are more. But for the test to assert the truth that its only correct when they match seems to be a mistake.
msg121289 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-11-16 13:25
I agree with Stephen.  The test in question is *not a valid test* on OSX.  Therefore on OSX it should be skipped.

If you can think of a way to test the actual behavior of getgroups on OSX, that's even better.
msg121291 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2010-11-16 13:44
Please explain how the failure can be reproduced.


I've done some testing on my machine using Apple's copy of python 2.6.1 (on OSX 10.6), which has the same getgroups implementation as the current heads of the active branches.


>>> os.getgroups()
[20, 402, 204, 61, 12, 401]
>>> os.system("id -G")
20 402 204 61 12 401
0

(Now open the Accounts preference pane and add a new user)


>>> os.getgroups()
[20, 403, 402, 204, 61, 12, 401]
>>> os.system("id -G")
20 403 402 204 61 12 401
0

Note how the result of both os.getgroups and id -G changes, which should mean that tests shouldn't fail unless you happened to add a new account in the split-second between the "calls" to os.getgroups and "id -G" in a testrun.

Was the buildbot started using launchd (the recipe at <http://buildbot.net/trac/wiki/UsingLaunchd> seems correct)? If not, how is it started?
msg121292 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-11-16 14:03
Having just reread this issue more carefully, my understanding is that Ronald had elected to make the results returned from os.getgroups match that returned by "system tools" (by which I understood him to mean the 'id' command).  Since Ronald reports he sees the intended behavior, Stephen's results seem to show that there is a problem with the fix in some circumstances which need to be understood.

Alexander noted that this should all be documented, and I agree, so I'm opening a new issue for the doc update.
msg121295 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2010-11-16 14:24
And it's entirely possible (even likely) that what Stephen is seeing here is a platform bug in OSX's quirky implementation of group management.
msg121312 - (view) Author: Stephen Hansen (ixokai) Date: 2010-11-16 20:04
On 11/16/10 5:44 AM, Ronald Oussoren wrote:
> Ronald Oussoren <ronaldoussoren@mac.com> added the comment:
> Please explain how the failure can be reproduced.

I have. But to do so more directly:

1. Launch Terminal.app; leave the window console open.
2. Run: id -G
3. Run: python
4. Type: import posix; posix.getgroups()
5. Go into System Preferences, add a user.
6. Type again, posix.getgroups(): notice, the values have not changed.
7. Either os.system("id -G") or ^D and type id -G: in either case, these
values *have* changed. Tested both.

> I've done some testing on my machine using Apple's copy of python 2.6.1 (on OSX 10.6), which has the same getgroups implementation as the current heads of the active branches.

As I said, the slave is running the latest on 10.5. Perhaps its a
platform bug which is fixed in 10.6: either way, the test is declaring
behavior is true that it shouldn't, I think.

Perhaps the test should only be skipped on 10.5? I am happy to provide a
patch which tests sys.platform == "darwin" and then runs sw_vars to make
only skip < 10.6.

I verified posix.getgroups() on 10.6 does not appear to exhibit this
behavior on my SL slave. However, that box does a LOT, so I can't vouch
for its 'purity' like the 10.5 box.

> Was the buildbot started using launchd (the recipe at <http://buildbot.net/trac/wiki/UsingLaunchd> seems correct)? If not, how is it started?

It was started with launchd, yes: with a variation of that recipe.
However as I stated, the behavior can be readily reproduced directly in
Terminal.
msg121333 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2010-11-17 02:11
The problem Stephen is seeing with the buildbot machine is ABI-dependent; the behavior of getgroups(2) changed in 10.6.  You can demonstrate this all on a 10.6 system.  Open a terminal session and verify the process's groups:

$ id -G
20 40200 401 204 100 98 80 61 12 403 40100 103
$ /usr/local/bin/python3.2 -c 'import posix; print(posix.getgroups())'
[20, 40200, 401, 204, 100, 98, 80, 61, 12, 403, 40100, 103]

Now create a new user with System Preferences.  One of the quirks here is that OS X 10.5 and 10.6 create a new group for that user and assign other existing users to that group.  (The new group is one of the somewhat mysteriously named com.apple.sharepoint.group.n groups.)

Still in the same terminal session after the new user/group was created and the existing user name we are running under was automatically added to the new group:
$ id -G
20 40200 401 204 100 98 80 61 12 403 40100 402 103
$ # note: new group membership 402 = com.apple.sharepoint.group.1
$ now test with 3 Pythons built from the same source, py3k tip:
$ cd ../../sdk10-4/py3k/
$ ./python -c 'import posix; print(posix.getgroups())'
[20, 40200, 401, 204, 100, 98, 80, 61, 12, 403, 40100, 103]
$ cd ../../sdk10-5/py3k/
$ ./python -c 'import posix; print(posix.getgroups())'
[20, 40200, 401, 204, 100, 98, 80, 61, 12, 403, 40100, 103]
$ cd ../../sdk10-6/py3k/
$ ./python -c 'import posix; print(posix.getgroups())'
[20, 40200, 401, 204, 100, 98, 80, 61, 12, 403, 40100, 402, 103]

Only the version built with a deployment target of 10.6 - that is, using the 10.6 SDK and the 10.6 ABI - reflects the updated grouplist.  And that difference can be seen, as Alexander noted earlier, in the symbols referenced.  An nm ./python | grep getgroups for each shows:
    U _getgroups$DARWIN_EXTSN
for the 10.6 deployment target version but
    U _getgroups
for the 10.5 and 10.4 targeted versions.

So unless building for a deployment target of 10.6 (or higher), it is to be expected that the output of /usr/bin/id will not match the results of getgroups(2) if the user's group membership changes during the run (as can happen when another user is created or deleted).

This particular problem should only be an issue when running on 10.5 and higher and using a 10.5 or earlier ABI.  On 10.4, neither getgroups(2) (as expected) nor /usr/bin/id see updates to group memberships made during the lifetime of the parent terminal session; starting a new login terminal session does see the updates.

Also note that this issue would be observable with all existing current python.org OS X installers running on 10.5 or 10.6 as most have been built with a 10.3 deployment target while 2.7 also provides an additional 32-/64-bit one with a 10.5 deployment target.  (I believe Ronald intends to build future 32-/64-bit installers with a 10.6 deployment target so they would be the first to not be subject to this issue.)

FTR, here are the configure options I used for each build:

./configure --enable-universalsdk=/Developer/SDKs/MacOSX10.4u.sdk --with-universal-archs=32-bit MACOSX_DEPLOYMENT_TARGET=10.4

./configure --enable-universalsdk=/Developer/SDKs/MacOSX10.5.sdk --with-universal-archs=intel MACOSX_DEPLOYMENT_TARGET=10.5

./configure --enable-universalsdk=/Developer/SDKs/MacOSX10.6.sdk --with-universal-archs=intel MACOSX_DEPLOYMENT_TARGET=10.6
msg121334 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2010-11-17 02:16
(Argh! Just to be very clear, those ./configure commands are all one line, including the MACOSX_DEPLOYMENT_TARGET as an argument to the configure script.)
msg130887 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2011-03-14 20:06
I'm closing this issue again, the current behavior is intended (as it mirrors platform behavior).
History
Date User Action Args
2011-03-14 20:06:58ronaldoussorensetstatus: open -> closed
nosy: loewis, ixokai, ronaldoussoren, belopolsky, orsenthil, pitrou, ned.deily, r.david.murray, flox, l0nwlf
messages: + msg130887
2011-02-05 09:29:06ned.deilylinkissue11124 superseder
2010-11-17 02:16:25ned.deilysetmessages: + msg121334
2010-11-17 02:11:55ned.deilysetnosy: + ned.deily
messages: + msg121333
2010-11-16 20:04:45ixokaisetmessages: + msg121312
2010-11-16 14:24:35r.david.murraysetmessages: + msg121295
2010-11-16 14:03:29r.david.murraysetmessages: + msg121292
2010-11-16 13:44:41ronaldoussorensetmessages: + msg121291
2010-11-16 13:26:43michael.foordsetnosy: - michael.foord
2010-11-16 13:25:14r.david.murraysetmessages: + msg121289
2010-11-16 07:52:42ixokaisetmessages: + msg121270
2010-11-16 07:41:24ronaldoussorensetmessages: + msg121269
2010-11-16 07:32:55r.david.murraysetmessages: + msg121267
2010-11-16 06:55:57ronaldoussorensetmessages: + msg121266
2010-11-11 22:39:36r.david.murraysetpriority: high -> normal
2010-11-11 22:39:17r.david.murraysetmessages: + msg120977
2010-11-11 22:09:09ixokaisetmessages: + msg120975
2010-11-11 22:03:34ronaldoussorensetmessages: + msg120974
2010-11-11 21:24:20ixokaisetstatus: closed -> open
2010-11-11 21:17:44ixokaisetnosy: + ixokai

messages: + msg120970
versions: + Python 3.1, Python 3.2
2010-08-03 08:08:52ronaldoussorensetstatus: open -> closed
2010-08-03 08:08:06ronaldoussorensetfiles: + smime.p7s

messages: + msg112563
2010-08-01 19:19:01ronaldoussorensetmessages: + msg112370
2010-08-01 18:48:48ronaldoussorensetmessages: + msg112365
2010-08-01 17:15:21pitrousetstatus: closed -> open
priority: normal -> high

nosy: + pitrou
messages: + msg112360
2010-07-24 10:06:09ronaldoussorensetstatus: open -> closed

messages: + msg111441
stage: patch review -> resolved
2010-07-23 16:08:22ronaldoussorensetresolution: accepted
messages: + msg111353
versions: - Python 3.1, Python 3.2
2010-07-23 13:13:44ronaldoussorensetmessages: + msg111310
2010-07-08 21:19:12belopolskysetmessages: + msg109608
2010-07-08 21:18:14belopolskysetmessages: + msg109607
2010-07-08 20:52:12ronaldoussorensetmessages: + msg109599
2010-07-08 20:38:59belopolskysetmessages: + msg109597
2010-07-08 20:30:25ronaldoussorensetmessages: + msg109593
2010-06-23 20:07:41loewissetmessages: + msg108483
2010-06-23 19:41:22r.david.murraysetmessages: + msg108482
2010-06-23 15:39:43belopolskysetmessages: + msg108456
2010-06-23 08:44:01ronaldoussorensetmessages: + msg108442
2010-06-23 00:19:08belopolskysetfiles: + issue7900-trunk.diff

messages: + msg108430
2010-06-22 21:46:00loewissetmessages: + msg108425
2010-06-22 15:16:36belopolskysetmessages: + msg108393
2010-05-07 16:58:55belopolskysetstage: test needed -> patch review
2010-05-06 05:23:59ronaldoussorensetfiles: + os-getgroups-v3.patch
2010-05-05 20:39:23belopolskysetmessages: + msg105086
2010-05-05 19:05:58ronaldoussorensetmessages: + msg105074
2010-05-05 18:41:30belopolskysetmessages: + msg105067
2010-05-05 18:22:56belopolskysetnosy: + belopolsky, - Alexander.Belopolsky
messages: + msg105065
stage: patch review -> test needed
2010-05-05 14:42:46ronaldoussorensetfiles: + os-getgroups-v2.patch
2010-05-05 14:42:20ronaldoussorensetmessages: + msg105042
2010-03-28 00:51:36michael.foordsetnosy: + michael.foord
messages: + msg101850
2010-03-28 00:51:01floxsetnosy: + flox
2010-02-24 18:02:50Alexander.Belopolskysetmessages: + msg100058
2010-02-24 17:45:00loewissetmessages: + msg100055
2010-02-23 22:42:26ronaldoussorensetmessages: + msg99964
2010-02-23 22:23:58ronaldoussorensetfiles: + getsetgroups-bug.tar

messages: + msg99962
2010-02-23 18:55:24Alexander.Belopolskysetmessages: + msg99944
2010-02-23 17:47:49Alexander.Belopolskysetmessages: + msg99941
2010-02-23 17:32:11ronaldoussorensetmessages: + msg99939
2010-02-23 17:22:46michael.foordsetnosy: - michael.foord
2010-02-23 17:16:13ronaldoussorensetmessages: + msg99935
2010-02-23 17:01:34Alexander.Belopolskysetmessages: + msg99933
2010-02-23 15:33:19Alexander.Belopolskysetmessages: + msg99928
2010-02-23 15:24:07Alexander.Belopolskysetmessages: + msg99926
2010-02-23 14:42:07Alexander.Belopolskysetmessages: + msg99919
2010-02-23 13:46:33ronaldoussorensetmessages: + msg99913
2010-02-23 13:42:31r.david.murraysetpriority: normal
2010-02-23 13:42:13r.david.murraysettype: crash -> behavior

messages: + msg99910
nosy: + r.david.murray
2010-02-23 13:28:35Alexander.Belopolskysetmessages: + msg99909
2010-02-23 13:18:29Alexander.Belopolskysetfiles: + issue7900-1.diff

messages: + msg99908
2010-02-23 08:29:12ronaldoussorensetfiles: + os-getgroups.patch

messages: + msg99903
stage: patch review
2010-02-23 07:20:53ronaldoussorensetmessages: + msg99901
2010-02-23 02:51:45Alexander.Belopolskysetfiles: + issue7900-tests.diff
2010-02-22 23:08:34Alexander.Belopolskysettype: behavior -> crash
messages: + msg99865
versions: + Python 2.6, Python 3.1, Python 3.2
2010-02-22 22:50:29Alexander.Belopolskysetfiles: + no-darwin-ext.diff

messages: + msg99862
2010-02-22 16:28:15Alexander.Belopolskysetfiles: + apple-2.6-fix-posixmodule.c.diff
2010-02-22 16:27:54Alexander.Belopolskysetfiles: + apple-2.5-fix-posixmodule.c.diff

messages: + msg99775
2010-02-22 16:17:39ronaldoussorensetmessages: + msg99772
2010-02-22 16:05:23Alexander.Belopolskysetmessages: + msg99766
2010-02-22 15:57:40Alexander.Belopolskysetfiles: + tg.py

messages: + msg99759
2010-02-21 22:29:12Alexander.Belopolskysetmessages: + msg99693
2010-02-21 18:58:36loewissetmessages: + msg99675
2010-02-20 20:43:34Alexander.Belopolskysetmessages: + msg99631
2010-02-20 20:43:25Alexander.Belopolskysetmessages: + msg99630
2010-02-20 20:21:31Alexander.Belopolskysetfiles: - issue7900.diff
2010-02-20 20:21:23Alexander.Belopolskysetfiles: + issue7900.diff
2010-02-20 20:14:08Alexander.Belopolskysetfiles: + issue7900.diff
keywords: + patch
messages: + msg99628
2010-02-20 19:13:55Alexander.Belopolskysetmessages: + msg99627
2010-02-20 18:37:07Alexander.Belopolskysetnosy: + Alexander.Belopolsky
messages: + msg99625
2010-02-19 05:06:14michael.foordsetmessages: + msg99556
2010-02-16 09:12:28ronaldoussorensetassignee: ronaldoussoren
messages: + msg99391
2010-02-16 09:08:03ronaldoussorensetmessages: + msg99390
2010-02-13 07:22:03l0nwlfsetmessages: + msg99310
2010-02-13 04:30:23l0nwlfsetmessages: + msg99307
2010-02-13 03:54:18orsenthilsetnosy: + loewis, ronaldoussoren, orsenthil, michael.foord
messages: + msg99306
2010-02-13 03:26:19l0nwlfsetnosy: - loewis, ronaldoussoren, orsenthil, michael.foord
messages: + msg99304
2010-02-12 18:29:52michael.foordsetmessages: + msg99279
2010-02-12 18:03:11orsenthilsetnosy: + orsenthil, ronaldoussoren
messages: + msg99277
2010-02-12 17:30:39l0nwlfsetnosy: + l0nwlf
messages: + msg99274
2010-02-10 15:04:56michael.foordcreate