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 -+-