[Top][All Lists]

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

Re: [PATCH] Port leak when using clisp

From: Justus Winter
Subject: Re: [PATCH] Port leak when using clisp
Date: Wed, 26 Aug 2015 13:18:47 +0200
User-agent: alot/0.3.5

Hi Flávio :)

Quoting Flávio Cruz (2015-08-26 01:46:16)
> Next, I started the bootstrapping process to compile SBCL but it would always
> fail with a kernel panic since Mach was unable to allocate more slabs for the
> ipc_port data structure. I figured out that the kernel had thousands of
> inactive ports (which had a single reference and one send-only right).

A very interesting find :)

> and the number of inactive ports in the kernel will increase (never 
> reclaimed),
> even when the CLISP process is killed. I've also attempted to use a separate
> partition and the ports would still hang around after the ext2fs translator 
> was
> terminated.

Indeed we have suspected that there is a bug like this for some time now.

> After looking around and using KDB, I've figured out that the following loop 
> in
> kern/exceptions.c/exception_raise_continue_slow was the culprit:

Could you elaborate a little on your method?

> while (mr == MACH_RCV_INTERRUPTED) {
> /*
> * Somebody is trying to force this thread
> * to a clean point.  We must cooperate
> * and then resume the receive.
> */
> while (thread_should_halt(self)) {
> /* don't terminate while holding a reference */
> if (self->ast & AST_TERMINATE)
> ipc_port_release(reply_port);
> thread_halt_self();
> }
> ip_lock(reply_port);
> ....
> }
> The reply port of the target thread (from CLISP?) is not being released since
> it enters the while(thread_should_halt(self)) loop and the thread terminates
> inside thread_halt_self but the previous condition does not hold, which fails
> to release the port. I also think that once the code enters thread_halt_self,
> it never comes back since the stack is discarded (for both if cases inside the
> function).

While I agree that the function thread_halt_self does not return, it
only terminates the thread if the AST_TERMINATE flag is set.
Otherwise, it returns to userspace.

> I've changed the code to make sure the port is released when 
> thread_should_halt
> is true. So far, the kernel works great and I was finally able to complete the
> second bootstrapping stage for SBCL. Please see the attached patch and let me
> know what you think.

Fwiw, I prefer inlined patches so I can reply easier ;)

> diff --git a/kern/exception.c b/kern/exception.c
> index 6cb3bfb..c68c5cb 100644
> --- a/kern/exception.c
> +++ b/kern/exception.c
> @@ -875,12 +875,10 @@ exception_raise_continue_slow(
>                *      and then resume the receive.
>                */
> -             while (thread_should_halt(self)) {
> -                     /* don't terminate while holding a reference */
> -                     if (self->ast & AST_TERMINATE)

Unless I'm missing something, you're basically removing this
conditional.  For me, it is not obvious that this is correct.  B/c now
we've given up our reference, return to userspace, and userspace is
likely re-trying the same again.  So when it does, isn't the reference
missing now?

> -                             ipc_port_release(reply_port);
> +             if (thread_should_halt(self))
> +                     ipc_port_release(reply_port);
> +             while (thread_should_halt(self))
>                       thread_halt_self();
> -             }

I find the use of `while' dodgy in the first place b/c if
thread_halt_self doesn't return, an if would do the trick as well and
don't imply the chance of that code looping...


reply via email to

[Prev in Thread] Current Thread [Next in Thread]