Hello, Zhaoming Luo, le lun. 10 mars 2025 16:44:09 +0800, a ecrit: > I haven't tested this patch again some stress tests as I don't know why > the `dpkg-buildpackage -B` on my qemu got stuck at: > > ``` > ... > ../scripts/evaluate-test.sh stdio-common/scanf14 $? false false > > /home/1speaker/apt-source/glibc-2.41/build-tree/hurd-i386-libc/stdio-common/scanf14.test-result > ```
It seems it is related: without your patch the test passes. Samuel > --- > sysdeps/mach/hurd/dup3.c | 62 +++++++++++++++++++++++++++++---------- > sysdeps/mach/hurd/fcntl.c | 52 ++++++++++++++++++++++++-------- > 2 files changed, 86 insertions(+), 28 deletions(-) > > diff --git a/sysdeps/mach/hurd/dup3.c b/sysdeps/mach/hurd/dup3.c > index 22af45b4..224a803c 100644 > --- a/sysdeps/mach/hurd/dup3.c > +++ b/sysdeps/mach/hurd/dup3.c > @@ -69,6 +69,7 @@ __dup3 (int fd, int fd2, int flags) > { > /* Get a hold of the destination descriptor. */ > struct hurd_fd *d2; > + error_t err; > > __mutex_lock (&_hurd_dtable_lock); > > @@ -107,22 +108,51 @@ __dup3 (int fd, int fd2, int flags) > } > else > { > - /* Give the ports each a user ref for the new descriptor. */ > - __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 slot. */ > - __spin_lock (&d2->port.lock); > - if (flags & O_CLOEXEC) > - d2->flags = d_flags | FD_CLOEXEC; > - else > - /* dup clears FD_CLOEXEC. */ > - d2->flags = d_flags & ~FD_CLOEXEC; > - _hurd_port_set (&d2->ctty, ctty); > - _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ > + /* Give the io server port a user ref for the new descriptor. */ > + err = __mach_port_mod_refs (__mach_task_self (), port, > + MACH_PORT_RIGHT_SEND, 1); > + > + if (err == KERN_UREFS_OVERFLOW) > + fd2 = __hurd_fail (EMFILE); > + else if (err) > + fd2 = __hurd_fail (EINVAL); > + else if (ctty != MACH_PORT_NULL) > + { > + /* We have confirmed the io server port has got a user ref > + count, now give ctty port a user ref for the new > + descriptor. */ > + err = __mach_port_mod_refs (__mach_task_self (), ctty, > + MACH_PORT_RIGHT_SEND, 1); > + > + if (err) > + { > + /* In this case the io server port has got a ref count > + but the ctty port fails to get ont, so we need to > + clean the ref count we just assigned. */ > + __mach_port_mod_refs (__mach_task_self (), port, > + MACH_PORT_RIGHT_SEND, -1); > + if (err == KERN_UREFS_OVERFLOW) > + fd2 = __hurd_fail (EMFILE); > + else > + fd2 = __hurd_fail (EINVAL); > + } > + } > + > + if (!err) > + { > + /* The ref counts of the ports are incremented > + successfully. */ > + /* Install the ports and flags in the new descriptor slot. */ > + __spin_lock (&d2->port.lock); > + if (flags & O_CLOEXEC) > + d2->flags = d_flags | FD_CLOEXEC; > + else > + /* dup clears FD_CLOEXEC. */ > + d2->flags = d_flags & ~FD_CLOEXEC; > + if (ctty != MACH_PORT_NULL) > + _hurd_port_set (&d2->ctty, ctty); > + _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ > + } > } > } > > diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c > index a65c190c..56d850e8 100644 > --- a/sysdeps/mach/hurd/fcntl.c > +++ b/sysdeps/mach/hurd/fcntl.c > @@ -83,18 +83,46 @@ __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, > - 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. */ > + /* Give the io server port a user ref for the new descriptor. */ > + err = __mach_port_mod_refs (__mach_task_self (), port, > + MACH_PORT_RIGHT_SEND, 1); > + > + if (err == KERN_UREFS_OVERFLOW) > + result = __hurd_fail (EMFILE); > + else if (err) > + result = __hurd_fail (EINVAL); > + else if (ctty != MACH_PORT_NULL) > + { > + /* We have confirmed the io server port has got a user ref > + count, now give ctty port a user ref for the new > + descriptor. */ > + err = __mach_port_mod_refs (__mach_task_self (), ctty, > + MACH_PORT_RIGHT_SEND, 1); > + > + if (err) > + { > + /* In this case the io server port has got a ref count > + but the ctty port fails to get one, so we need to clean > + the ref count we just assigned. */ > + __mach_port_mod_refs (__mach_task_self (), port, > + MACH_PORT_RIGHT_SEND, -1); > + if (err == KERN_UREFS_OVERFLOW) > + result = __hurd_fail (EMFILE); > + else > + result = __hurd_fail (EINVAL); > + } > + } > + > + if (!err) > + { > + /* The ref counts of the ports are incremented successfully. */ > + /* Install the ports and flags in the new descriptor. */ > + if (ctty != MACH_PORT_NULL) > + _hurd_port_set (&new->ctty, ctty); > + new->flags = flags; > + /* Unlocks NEW. */ > + _hurd_port_locked_set (&new->port, port); > + } > } > > HURD_CRITICAL_END; > -- > 2.47.2 > -- Samuel <N> bon comment on fait de l'investigation pour savoir qui est le vilain ? <s> on débranche le routeur et on regarde qui s'affole -+- #ens-mim administre -+-