[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: proc leaking



Sergey Bugaev, le mer. 01 nov. 2023 23:18:01 +0300, a ecrit:
> On Wed, Nov 1, 2023 at 9:17 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > I tracked it a bit, it seems that libport is not always cleaning
> > structures from the proc class. Below is the tracing that we get for
> > instance with the while loop above. Alloc is the allocation of pi, free
> > is the freeing from the point of view of the proc server, and clean is
> > the actual cleanup done by libports.
> >
> > Could it be that proc is overflown with dead port notifications? That's
> > not many procs, but still. Maybe Sergey has an idea?
> 
> I don't think I understood what "freeing from the point of view of the
> proc server" and "actual cleanup done by libports" mean (for one
> thing, proc_class's clean_routine is NULL).

>From the point of view of the proc server = complete_exit was called
Actual cleanup = clean_routing called (I added one just to track it).

The difference between the two is probably some remaining port
reference for whatever reason.

> Perhaps you could post this as a patch to clear things up, and also
> for me to try and reproduce (& debug) this?

Here it is.

Samuel
diff --git a/proc/main.c b/proc/main.c
index 747646ef..8a74c14d 100644
--- a/proc/main.c
+++ b/proc/main.c
@@ -165,6 +165,20 @@ parse_opt (int key, char *arg, struct argp_state *state)
   return 0;
 }
 
+extern long proc_alloc;
+extern long proc_clean;
+extern long proc_free;
+static void clean_proc(void *p)
+{
+	proc_clean++;
+  if ((proc_clean % 100) == 0)
+  {
+	  char s[128];
+	  snprintf(s, sizeof(s), "proc: alloc %lu free %lu clean %lu\n", proc_alloc, proc_free, proc_clean);
+	  mach_print(s);
+  }
+}
+
 int
 main (int argc, char **argv, char **envp)
 {
@@ -185,7 +199,7 @@ main (int argc, char **argv, char **envp)
     error (2, 0, "proc server can only be run by startup during boot");
 
   proc_bucket = ports_create_bucket ();
-  proc_class = ports_create_class (0, 0);
+  proc_class = ports_create_class (clean_proc, 0);
   generic_port_class = ports_create_class (0, 0);
   exc_class = ports_create_class (exc_clean, 0);
   ports_create_port (generic_port_class, proc_bucket,
diff --git a/proc/mgt.c b/proc/mgt.c
index f87daeb3..fa19e8d7 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -43,6 +43,7 @@
 #include "proc_exc_U.h"
 #include "task_notify_S.h"
 #include <hurd/signal.h>
+#include <stdio.h>
 
 extern mach_msg_return_t
 mach_msg_receive (mach_msg_header_t *msg);
@@ -794,6 +795,10 @@ S_proc_getallpids (struct proc *p,
   return 0;
 }
 
+
+long proc_alloc;
+long proc_clean;
+long proc_free;
 /* Create a process for TASK, which is not otherwise known to us.
    The PID/parentage/job-control fields are not yet filled in,
    and the proc is not entered into any hash table.  */
@@ -810,6 +815,13 @@ allocate_proc (task_t task)
   err = ports_create_port (proc_class, proc_bucket, sizeof (struct proc), &p);
   if (err)
     return NULL;
+  proc_alloc++;
+  if ((proc_alloc % 100) == 0)
+  {
+	  char s[128];
+	  snprintf(s, sizeof(s), "proc: alloc %lu free %lu clean %lu\n", proc_alloc, proc_free, proc_clean);
+	  mach_print(s);
+  }
 
   memset (&p->p_pi + 1, 0, sizeof *p - sizeof p->p_pi);
   p->p_task = task;
@@ -1158,6 +1170,13 @@ complete_exit (struct proc *p)
      will shortly vanish (because we are p_dead, those routines do
      nothing).  */
   ports_port_deref (p);
+  proc_free++;
+  if ((proc_free % 100) == 0)
+  {
+	  char s[128];
+	  snprintf(s, sizeof(s), "proc: alloc %lu free %lu clean %lu\n", proc_alloc, proc_free, proc_clean);
+	  mach_print(s);
+  }
 }
 
 /* Get the list of all tasks from the kernel and start adding them.

Reply to: