This patch is quite conservative, only the first mach_port_mod_ref() is
checked, as I haven't found an elegant way to check both
mach_port_mod_ref()s.

I haven't successfully tested this patch. I have tried several methods to
apply the patch and build but failed:

- Clone the glibc source code, try to build with '--prefix=' and
  '--prefix=/usr', and `sudo make install`. The results were a broken
  system. I cannot run any command, it just output 'XXX.so file not
  found'.

- Run 'apt source glibc', use quilt to apply this patch and build
  the libc package using `dpkg-buildpackage -B`. I got the same error as
  [0].

[0]: 
https://buildd.debian.org/status/fetch.php?pkg=glibc&arch=hurd-i386&ver=2.41-3&stamp=1740910186&raw=0

- Run 'apt source glibc=2.40-7' (as I found this is the newest
  successful build on the website). I have successfully built a glibc
  once, but after a `apt upgrade` it failed with the following output:
```
...
/usr/bin/ld: /lib/i386-gnu/liblzma.so.5: undefined reference to 
`pthread_sigmask@GLIBC_2.41'
/usr/bin/ld: /lib/i386-gnu/liblzma.so.5: undefined reference to 
`pthread_condattr_setclock@GLIBC_2.41'
collect2: error: ld returned 1 exit status
...
```

Maybe some downgrade is needed?

I'm not very familiar with the Debian building system, maybe I mis-read
something in the package building tutorial.

Best,
Zhaoming
---
 sysdeps/mach/hurd/fcntl.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c
index a65c190c..d97226cd 100644
--- a/sysdeps/mach/hurd/fcntl.c
+++ b/sysdeps/mach/hurd/fcntl.c
@@ -83,18 +83,34 @@ __libc_fcntl (int fd, int cmd, ...)
          result = -1;
        else
          {
-           /* Give the ports each a user ref for the new descriptor.  */
-           __mach_port_mod_refs (__mach_task_self (), port,
+           /* Give the ports (i.e. `ctty` and `port`) each a user ref for
+              the new descriptor.  */
+           err = __mach_port_mod_refs (__mach_task_self (), port,
                                  MACH_PORT_RIGHT_SEND, 1);
-           if (ctty != MACH_PORT_NULL)
-             __mach_port_mod_refs (__mach_task_self (), ctty,
-                                   MACH_PORT_RIGHT_SEND, 1);
-
-           /* Install the ports and flags in the new descriptor.  */
-           if (ctty != MACH_PORT_NULL)
-             _hurd_port_set (&new->ctty, ctty);
-           new->flags = flags;
-           _hurd_port_locked_set (&new->port, port); /* Unlocks NEW.  */
+
+           if (err)
+             {
+               /* When an error occurs during giving a user ref to the
+                  io server port */
+               result = -1;
+
+               if (err == KERN_UREFS_OVERFLOW)
+                 errno = EMFILE;
+               else
+                 errno = EINVAL;
+             }
+           else
+             {
+               if (ctty != MACH_PORT_NULL)
+                 __mach_port_mod_refs (__mach_task_self (), ctty,
+                         MACH_PORT_RIGHT_SEND, 1);
+
+               /* Install the ports and flags in the new descriptor.  */
+               if (ctty != MACH_PORT_NULL)
+                 _hurd_port_set (&new->ctty, ctty);
+               new->flags = flags;
+               _hurd_port_locked_set (&new->port, port); /* Unlocks NEW.  */
+             }
          }
 
        HURD_CRITICAL_END;
-- 
2.47.2


Reply via email to