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: