I'm looking at Ticket # 5365 (Process.gid= fails on OS X) at:

     http://rubyforge.org/tracker/? 
func=detail&atid=1698&aid=5365&group_id=426

and am poking at process.c. There are some problems with either the  
implementation and/or the documentation for it. To summarize:

1) Documentation doesn't agree with implementation - might want to  
state only sets to egid.
2) setregid is not recommended for use.
3) rb_notimplemented used for a permissions error.
4) root can't set to anything but effective gid. We should let the  
system decide.

#1:

The doco states:

     Sets the group ID for this process.

But the implementation only does a setgid if the desired gid is the  
effective gid. Given change_privilege, I think it is the doco that is  
wrong. Please confirm.

#2/3:

With regard to the implementation, it is preferring setregid over  
setegid/setgid, but my man page states (on both darwin and freebsd):

      The setregid() function was intended to allow swapping the real  
and
      effective group IDs in set-group-ID programs to temporarily  
relinquish
      the set-group-ID value.  This function did not work correctly,  
and its
      purpose is now better served by the use of the setegid()  
function (see
      setuid(2)).

      When setting the real and effective group IDs to the same  
value, the
      standard setgid() function is preferred.

So maybe we should prefer the following change:

--- process.c	06 Aug 2006 16:10:26 -0700	1.92.2.33
+++ process.c	14 Aug 2006 12:19:16 -0700	
@@ -2494,9 +2494,7 @@
      check_gid_switch();
#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
      if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
-    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRGID
+#elif defined _WIN32 && !defined __CYGWIN__ && defined HAVE_SETRGID
      if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
      {
@@ -2504,7 +2502,7 @@
	    if (setgid(gid) < 0) rb_sys_fail(0);
	}
	else {
-	    rb_notimplement();
+	    rb_raise(rb_eSecurityError, "gid (%d) is not equal to the  
effective group id", gid);
	}
      }
#else

Note also that I changed the rb_notimplemented to be a correct error  
message for the situation.

#4:

If the doco is fine and #gid= should be able to set the gid, then we  
should probably take out the effective gid check entirely and let the  
system call do it. The man page says that you should be able to set  
to whatever you want if you are root:

      [EPERM]            The current process is not the super-user  
and a change
                         other than changing the effective group-id  
to the real
                         group-id was specified.

But our implementation doesn't allow for that. This does:

--- process.c	06 Aug 2006 16:10:26 -0700	1.92.2.33
+++ process.c	14 Aug 2006 12:20:52 -0700	
@@ -2494,18 +2494,11 @@
      check_gid_switch();
#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
      if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
-    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRGID
+#elif defined _WIN32 && !defined __CYGWIN__ && defined HAVE_SETRGID
      if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0);
#elif defined HAVE_SETGID
      {
-	if (getegid() == gid) {
-	    if (setgid(gid) < 0) rb_sys_fail(0);
-	}
-	else {
-	    rb_notimplement();
-	}
+        if (setgid(gid) < 0) rb_sys_fail(0);
      }
#else
      rb_notimplement();

Please tell me what you guys prefer and I'll get it tested and  
committed.