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

Re: wakeup events.. thoughts?



On Sat, Aug 28, 1999 at 04:48:12PM -0700, Andrew Morgan wrote:
> Savochkin Andrey Vladimirovich wrote:
> > How to pass the event information is a not very important question for me.
> > The module may set the information by a special library call before returning
> > PAM_WAIT_EVENT.  Or the library may ask the module about this information by
> > a special call seeing PAM_WAIT_EVENT.
> 
> Ouch, you are a little ahead of me here! This complicates matters a lot.
> It seems to capture some more general aspect of
> PAM_CONV_AGAIN/PAM_INCOMPLETE thing. In so far as the module has not
> completed but, for whatever reason, it wants to hand back control until
> an event occurs. Do you mean this could be before the
> session_open+fork()?

Well, I was too quick and brief :-)

Let's consider the proposed main loop in applications:
        pid = fork();
        if (!pid) do_child();
        while (1) {
            [establish_credentials]
            [resume child]
            retval = pam_event()
            [delete_credentials]
            if (retval == PAM_SESSION_EXIT)
                break;
            [reauthenticate]
        }

pam_event() should wait until some module reports about a significant event
(withdrawing a smartcard, expiration of a ticket etc).

I see two options here:
 - make pam_sm_event() interface (from the library to modules) completely
   different from e.g. pam_sm_authenticate().
   pam_sm_event() returns a structure describing what to wait for and
   a callback for a case a desired event happens.
   The callback may return to the library "continue waiting" or "return back
   to the application with the following result".

   Going back to the question who asks whom: the library asks modules what to
   wait for (considering pam_sm_event call) or modules asks library to wait
   for particular events (considering the return value).
   Who asks whom is only a terminological question for the case.

 - make pam_sm_event() interface similar to pam_sm_authenticate().
   It means that the module call return a definitive answer (terminate the
   session immediately) or asks the library to call the module later
   (specifying when to call: after a poll event or a timeout).

   This approach has a stylistic advantage (interfaces are
   similar) and allows IO oriented modules to wait for completion of some
   operation simultaneously.

I definitely would prefer #2 if modules were equivalent.
With different options of module loading ("required", "requisite" etc)
#2 looks less natural.

What do you think about this two models?


> > [pthreads, xxx-threads, which ones? Portability, inefficiency and bad
> >  experiences... too early to commit to one or other flavor under Linux.]
> 
> I am inclined to agree with this analysis. Sun on the other hand are as
> happy as clams with posix-threads, and are keenly embedding them in
> their modules... What I'd like to see is us contribute to an API that we
> can support/maintain given Linux as-is and they can support too. I'd
> like it to not preclude the use of (any flavor) of threads, so they
> don't reject the API, and yet be simple enough that without libpam
> knowing about threads, a careful Linux module/app programmer could use
> it with clone() or whatever and get their job done.

Agreed.
But the problem is how to support waiting for a variable change in libpam?
The support (if we add it) should be just in libpam, not somewhere else.
And we agreed that libpam should not know too much about threads in the
nearest future (just keeping libpam code reenterable etc).

> 
> > The idea of conditional variables doesn't look good to me at the moment.
> > Waiting on a variable will require either
> >  - CPU consuming busy loop (very bad)
> >  - spawning threads (not so good)
> >  - or use existing implementation which implements one of the methods above.
> 
> My impression was that Solaris has some sort of kernel support for this
> 'wake on memory write'. I could be wrong.

8-0

That's possible (special pagefault handlers etc) but not very easy to
implement efficiently.   If we get such a kernel support we may support
"waiting on a variable" in libpam too.

Well, we may agree with Sun about some API for "waiting on a variable" in
additional to poll()ing.  But I don't think we can support it now.

> 
> > etc).  So threads in a library like libpam looks impractical at this stage.
> 
> I certainly do not think we need to have threads spawned and running in
> parallel within libpam any time soon, but I would like to think that
> modules and applications could have them - provided they abide by the
> one pamh per thread that calls into libpam rule.
> 
> Here is a list of event_types that we've discussed:
> 
>  PAM_EVENT_TIME_RELATIVE (*) [RELATIVE and ABSOLUTE?]
			relative looks sufficient
>  PAM_EVENT_FILDES_SELECT (*) [Do we need read/write specificity?]
			I prefer to specify what to wait for.
			A socket may be permanently ready to accept new data
			but I want to wait for data being ready.
>  PAM_EVENT_CHILD_EXIT        [More generally, handle any signal]
>  PAM_EVENT_MEMORY_WRITE      [The essence of conditional variables]
> 
> The (*) ones are supported by select()/poll(). The CHILD_EXIT one
> will/may generate a signal, and is probably limited to an
> 'application-specific' event and not something we want a module to be
> doing much of. The MEMORY_WRITE event is something we do not have kernel

A module waiting for a child exit is a usual situation.
Some kind of support is desired.

> support for, but which might be usable for modules trying to manage
> threads (of whatever flavor).
> 
> _If_ we had some efficient way of supporting the last one, we could
> obviate the need for the CHILD_EXIT event. Namely, we'd require that
> whoever launched the child needs to handle its exit and then do a write
> to some pre-registered memory location (all done within a signal_handler
> perhaps?).

The special event CHILD_EXIT looks better.
What if two modules spawn children?  The second module overrides a handler of
the previous one and bad things start.

Well, we don't even need _two_ such modules.  The application waits for a
child too.
What do you think if the application informs libpam about waiting a child
before pam_event() call and the library will handle SIGCHLD?

Otherwise it isn't safe for modules to touch signal handlers at all.

> 
> The flow of control being that the application has called
> pam_await_event(), the child dies, the application receives a signal
> who's handler writes to a memory location announcing that this
> PAM-relevant event has occurred and then the signal handler exits,
> returns control to pam_await_event(), which sees that the memory is
> written, and takes the appropriate action for that event.
> 
> All that does start with an _if_ though. Without kernel support, it
> looks like some sort of busy-wait is the only way we could do this. We
> could do a little better than blindly hogging the CPU by doing a
> semi-busy-wait within libpam with say a one second granularity, and just
> have a little delay picking up the phone when some memory is altered.
> (In the case of the child dying, our select/poll call would return early
> so we'd not be that slow to notice this type of event.)

I would prefer to support child exits normally from the beginning.
Waiting on variables may be implemented via semi-busy-wait or kept
unsupported for a while.

> 
> In the case of smart cards, the hardware/drivers are not always created
> with select() type of symantics in mind. My limited experience so far is
> that you need to probe them frequently to establish their current state.

An insane semantics for me :-)
I've seen such things in Windoze world.  Have you tried playing a realtime
game and printing at the same time?
Once I launched a printing job on a station where my friend was playing.
Unforgettable impression (for both of us)...
I suppose just because of probing.

> 
> Finally, we should also support applications with their own event loop,
> we could have a non-blocking way of invoking pam_await_timer(), that
> returns immediately if there are no events pending.

I prefer applications to add their own events for pam_await_event().
Busy loops su.. hmm not very efficient.

Best wishes
		Andrey



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