Hello,

On Sun, 8 Nov 2026 16:44:29 Samuel Thibault wrote:

> > Also, what is the correct way to deallocate a port_bucket? Judging by
> > create-bucket.c, a single call to free (port_bucket) is not sufficient.
>
> It seems so, according to the hurd_ihash_destroy call at least.
>
> > Perhaps it would be worth adding a dedicated function for this in libports?
>
> Yes, it should have been done already :)
>
> It should probably assert that the ihash is already empty and the
> threadpool is empty.

I think we can do it this way.

Thanks,

--
Mikhail Karpov
From b766cbc05d64c3be338a02c96c25fb87034f99f4 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Mon, 9 Nov 2026 12:43:05 +0700
Subject: [PATCH 2/3] Added a function that destroys a bucket

---
 libports/Makefile         |  2 +-
 libports/create-bucket.c  | 10 ++++------
 libports/destroy-bucket.c | 33 +++++++++++++++++++++++++++++++++
 libports/ports.h          |  3 +++
 4 files changed, 41 insertions(+), 7 deletions(-)
 create mode 100644 libports/destroy-bucket.c

diff --git a/libports/Makefile b/libports/Makefile
index c67d8fe..bc95330 100644
--- a/libports/Makefile
+++ b/libports/Makefile
@@ -21,7 +21,7 @@ dir := libports
 makemode := library
 
 libname = libports
-SRCS = create-bucket.c create-class.c \
+SRCS = create-bucket.c create-class.c destroy-bucket.c \
  reallocate-port.c reallocate-from-external.c destroy-right.c \
  lookup-port.c port-ref.c port-ref-weak.c port-deref.c port-deref-weak.c \
  no-senders.c begin-rpc.c end-rpc.c manage-one-thread.c manage-multithread.c \
diff --git a/libports/create-bucket.c b/libports/create-bucket.c
index 4c82786..0e291d7 100644
--- a/libports/create-bucket.c
+++ b/libports/create-bucket.c
@@ -42,10 +42,7 @@ ports_create_bucket (void)
 
   ret = malloc (sizeof (struct port_bucket));
   if (! ret)
-    {
-      errno = ENOMEM;
-      return NULL;
-    }
+    return NULL;
 
   err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, 
 			    &ret->portset);
@@ -63,10 +60,11 @@ ports_create_bucket (void)
   /* Create the notify_port for this bucket.  */
   pthread_once (&init_notify_port_class_once, init_notify_port_class);
   err = ports_create_port (notify_port_class, ret,
-                           sizeof (struct port_info),
-                           &ret->notify_port);
+			   sizeof (struct port_info),
+			   &ret->notify_port);
   if (err)
     {
+      mach_port_deallocate (mach_task_self (), ret->portset);
       hurd_ihash_destroy (&ret->htable);
       free (ret);
       errno = err;
diff --git a/libports/destroy-bucket.c b/libports/destroy-bucket.c
new file mode 100644
index 0000000..4909b16
--- /dev/null
+++ b/libports/destroy-bucket.c
@@ -0,0 +1,33 @@
+/* Destroy the bucket.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   The GNU Hurd is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include "ports.h"
+
+void
+ports_destroy_bucket (struct port_bucket *bucket)
+{
+  assert_backtrace (bucket->htable.nr_items == 0);
+  assert_backtrace (bucket->threadpool.old_threads == 0
+                    && bucket->threadpool.young_threads == 0);
+
+  mach_port_deallocate (mach_task_self (), bucket->portset);
+  ports_port_deref (bucket->notify_port);
+  hurd_ihash_destroy (&bucket->htable);
+  free (bucket);
+}
diff --git a/libports/ports.h b/libports/ports.h
index 072c8a0..b946618 100644
--- a/libports/ports.h
+++ b/libports/ports.h
@@ -175,6 +175,9 @@ struct port_bucket *ports_create_bucket (void);
 struct port_class *ports_create_class (void (*clean_routine)(void *),
 				       void (*dropweak_routine)(void *));
 
+/* Destroy the BUCKET.  */
+void ports_destroy_bucket (struct port_bucket *bucket);
+
 /* Create and return in RESULT a new port in CLASS and BUCKET; SIZE bytes
    will be allocated to hold the port structure and whatever private data the
    user desires.  */
-- 
2.43.0

From 92bdbee83b8d8fc10c96183a0988955d7d565691 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Mon, 9 Nov 2026 12:44:54 +0700
Subject: [PATCH 3/3] Added check for ports_create_bucket in storeio/pager.c

---
 storeio/pager.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/storeio/pager.c b/storeio/pager.c
index 7a26efa..8e0bc4b 100644
--- a/storeio/pager.c
+++ b/storeio/pager.c
@@ -145,9 +145,10 @@ static struct port_bucket *pager_port_bucket = 0;
 static struct pager_requests *pager_requests;
 
 /* Initialize paging for this device.  */
-static void
+static error_t
 init_dev_paging (void)
 {
+  error_t err = 0;
   if (! pager_port_bucket)
     {
       static pthread_mutex_t pager_global_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -155,20 +156,30 @@ init_dev_paging (void)
       pthread_mutex_lock (&pager_global_lock);
       if (pager_port_bucket == NULL)
 	{
-	  error_t err;
-
-	  pager_port_bucket = ports_create_bucket ();
+	  struct port_bucket *bucket = ports_create_bucket ();
+	  if (! bucket)
+	    {
+	      err = errno;
+	      error (0, err, "ports_create_bucket");
+	      goto out;
+	    }
 
 	  /* Start libpagers worker threads.  */
-	  err = pager_start_workers (pager_port_bucket, &pager_requests);
+	  err = pager_start_workers (bucket, &pager_requests);
 	  if (err)
 	    {
-	      errno = err;
+	      ports_destroy_bucket (bucket);
 	      error (0, err, "pager_start_workers");
 	    }
+	  else
+	    pager_port_bucket = bucket;
 	}
+
+     out:
       pthread_mutex_unlock (&pager_global_lock);
     }
+
+  return err;
 }
 
 void
@@ -229,7 +240,9 @@ dev_get_memory_object (struct dev *dev, vm_prot_t prot, memory_object_t *memobj)
     {
       int created = 0;
 
-      init_dev_paging ();
+      err = init_dev_paging ();
+      if (err)
+	return err;
 
       pthread_mutex_lock (&dev->pager_lock);
 
-- 
2.43.0

Reply via email to