Hi,

The curl testsuite 537 does not fail, but it output a lot of
'deallocating a bogus port...' on the terminal.

Test 537 on Hurd opens 0x40000 file discriptors and close them[0]. The
initial max number of file discriptor on Hurd is 1024[1]. Test 537 raises
this number to unlimited so it won't be terminated[2].

[0]: https://github.com/curl/curl/blob/master/tests/libtest/lib537.c#L268
[1]: run `ulimit -n` to see
[2]: https://github.com/curl/curl/blob/master/tests/libtest/lib537.c#L181-L182

Test 537 uses dup() to open a lot of file discriptors[3]. In this case,
The reference count of the port of the discriptor is incremented whenever
a dup() is executed[4]. The code line of [4] I think is where the issue
is. We ignored return value of __mach_port_mod_refs(). In this case we
indeed reached the limit of reference count[5], but the test 537
supposed a new file discriptor was still allocated. Therefore, when the
reference count is down to 0 and the port is freed, the test 537 thought
there are still file discriptors needed to be freed.

[3]: https://github.com/curl/curl/blob/master/tests/libtest/lib537.c#L334
[4]: 
https://sourceware.org/git?p=glibc.git;a=blob;f=sysdeps/mach/hurd/fcntl.c;h=a65c190cac3377e644b0a8a729cc6f69d527b32f;hb=HEAD#l87
[5]: https://git.savannah.gnu.org/cgit/hurd/gnumach.git/tree/ipc/port.h#n77

The following code can reproduce the issue:
```
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/resource.h>

#define FILE_NUM 65536

int
main ()
{
  int fds[FILE_NUM];
  int fd = open ("tmp", O_CREAT, O_RDONLY);

  struct rlimit rl;

  if(getrlimit(RLIMIT_NOFILE, &rl) != 0) {
    printf ("getrlimit() failed\n");
    return 0;
  }

  rl.rlim_cur = rl.rlim_max;

  if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
    printf ("setrlimit() failed\n");
    return 0;
  }

  if (fd == -1)
    {
      printf ("open() failed!\n");
      return 0;
    }

  printf ("fd is %d!\n", fd);

  for (int i = 0; i < FILE_NUM; i++)
    {
      int newfd = dup (fd);

      if (newfd == -1)
        {
          printf ("dup() failed!\n");
          return 0;
        }

      fds[i] = newfd;

      printf ("Just opened fd %d\n", newfd);
    }

  for (int i = 0; i < FILE_NUM; i++)
    {
      int err = close (fds[i]);

      if (err == -1)
        {
          printf ("close() failed!\n");
          return 0;
        }

      printf ("Just closed fd %d\n", fds[i]);
    }

  printf ("All done\n");

  return 0;
}
```

Best,
Zhaoming


Reply via email to