tech-kern archive

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

Re: Problem with syscall_disestablish() - PR kern/50430



On Thu, Nov 19, 2015 at 1:43 PM, Paul Goyette <paul%vps1.whooppee.com@localhost> wrote:
> On Thu, 19 Nov 2015, Masao Uebayashi wrote:
>
>> On Wed, Nov 18, 2015 at 11:07 AM, Paul Goyette <paul%vps1.whooppee.com@localhost>
>> wrote:
>>>
>>> Based on earlier comments, I've come up with a much-less-intrusive
>>> set of changes.  This time around, there are no bit masks and no new
>>> members in any system structures.  (I'm pretty sure we won't even
>>> need a kernel version bump for this.)
>>>
>>> Instead, I've modified sy_call() to check the current value of
>>> l_sysent before updating with the new syscall pointer.  If the
>>> current value is non-NULL then set a new flag bit LP_LOST_SYSENT in
>>> the lwp's l_pflag member.  This check is the only per-syscall cost:
>>>
>>>         if (l->l_sysent != NULL)
>>>                 l->l_pflag |= LP_LOST_SYSENT;
>>
>>
>> My understanding is that l_sysent is *always* overriden by syscalls
>> from within signal handlers, right?
>
>
> It's not a question of "being overwritten".  The real situation is
> that the _initial_ syscall returns first (with ERESTART), and l_sysent
> is reset to NULL.  Then when the signal handler calls some other
> syscall, there is nothing to lose.

I think I understand these now ... I misunderstood that signal is
delivered (signal handler is called) first then kernel stack from
tsleep() is returned back to syscall() ... I am so stupid. :(

I also realize that grasping the big picture of signal delivery is not
difficult once understood ... but still confusing as I wrote in the
other mail.  (I wish I could have understand these 10 years ago.)

You can close the PR.

>
> Then, when the handler returns, the _original_ syscall is automatically
> restarted.
>
> As I said earlier, I have not identified the exact code where all of
> this happens.  But empirical evidence (from printf()s inserted in
> sy_call() both before and after the dispatch) shows that it works as
> I've described.  There was never any non-NULL value in l_sysent at
> the point where sy_call() stores a new value.  And the printf() I
> had inserted after the syscall dispatch clearly showed a return value
> of -3 == ERESTART.
>
>
>> I don't fully understand these things yet, but ... my gut feeling is
>> that l_sysent should be saved on stack in mi_switch(), like oldspl,
>> before cpu_switchto(), and restored after that.  In resuming code
>> path, check if syscall exists, in case syscall was forcibly
>> disestablished.  If it doesn't exist, forcibly kill self lwp ... maybe
>> using sigexit()?
>
>
> I'm expecting that the old l_sysent is being saved on the stack by
> the signal code;  I just don't know where (since there doesn't seem
> to be any such reference to l_sysent!).
>
> When the syscall gets restarted, it will get auto-loaded again if it
> has been disestablished, so nothing is lost.
>
>> (I believe someone from CS department understand such things 100% and
>> correct me if wrong. ;)
>
>
>
> +------------------+--------------------------+-------------------------+
> | Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:       |
> | (Retired)        | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com    |
> | Kernel Developer | 0786 F758 55DE 53BA 7731 | pgoyette at netbsd.org  |
> +------------------+--------------------------+-------------------------+


Home | Main Index | Thread Index | Old Index