[Fresco-devel] Re: [eros-arch] Fresco?

"Jonathan S. Shapiro" <[email protected]>
Newsgroups gmane.comp.video.fresco.devel
Message-ID <[email protected]>
Reminder to eros-arch readers: our mailing lists set reply-to, so please
remember to add fresco-devel at fresco.org when appropriate.


On Tue, 2002-12-31 at 05:56, Nathaniel Smith wrote:
> The issue here is whether Fresco can 1) make
> sure to use only memory borrowed from clients when allocating objects
> on the behalf of clients, and 2) deal reasonably if that memory
> suddenly disappears.

I think you've got the essence of it. I want to go into a little more
detail to be sure, but sounds like you have the right flavor. I hadn't
caught that scene maps could be remote. The need to deal with that
certainly means you have to deal with essentially the same issues.

> (1) is easy -- in the case of client crash, we have to be
> able to jettison all of the client's state, which means that
> allocations already have to know which client they're being performed
> on the behalf of.  Modifying this to use a special per-client
> allocator wouldn't be a terribly big change...

Provided that there is no storage optimization whose result is to share
state across clients, this seems likely to work. As you say, recursive
allocations need to be done in the correct user context. I would suggest
that the best way to get this right in practice is to invert the
problem:

1. Make the "per-client heap" part of the per-connection information.
2. Have all allocation calls use the per-client heap in the normal case
3. Override this when you really mean to be allocating memory from the
server heap.

Then you need to locate all case (3) allocations in your code that arise
from user calls and abolish them unless the total allocation is bounded
(i.e. absolutely won't allocate more than K bytes for some K, no matter
what) and ephemeral (won't survive past the current invocation). You'll
need some of this for connection setup, for example. Given that you are
using C++, this is going to be hard because there aren't any good static
analysis tools available for you to use -- this is one of the reasons we
abandoned C++ for the EROS kernel (the other being that the GNU
compilers are too unstable, and we finally gave up).

Shared state is of course okay if the state being shared is a predefined
read-only resource supplied by the server, such as (perhaps) a
primordial color map.

> it'd require some tweaking of STL and some extra
> memory overhead (since every object would need to keep track of which
> space bank it should allocate out of).

STL may not need to be tweaked directly. You might instead whack the
global ::new() implementation and keep the "current heap" value in a
thread-local global variable. A collection class that contains
heterogeneous elements referenced by strong pointers is invariably an
error, though. You might want to hack STL to allow you to check this for
debugging purposes.

Depending on your allocator, there may be no need to keep any more
per-object state than you already have, since most allocators these days
keep book-keeping information in a per-object header. In any case, this
is indeed object header information. It will occupy space, but shouldn't
change the visible semantics of your objects.

> (2) I'm less sure about, because I don't know exactly what happens
> when a client shoots its space bank -- does the next attempt to
> traverse a pointer into that memory throw a nice exception (assuming
> C++ here, because that's what Fresco is written in), or what?

Exactly.

More precisely, there are two cases that can arise:

1. Client does an orderly shutdown. In this case you get to clean up, so
presumably the client heap is empty by the time you unmap it. You will,
of course, want to check this explicitly. The Boehm GC could easily be
modified for this purpose if you haven't already got a technology for
doing this.

2. Client gets its space reclaimed out from under it. In this case the
client heap is forcibly unmapped without any action on your part, and
you'll see memory exceptions. Note this means that destructors and
finalizers will NOT be called -- the client no longer has the authority
to use the memory in which they would run. Given that Fresco allows
remote maps that can spontaneously disappear, I would say that it is a
design error to rely on the execution of any finalizer or destructor for
any purpose other than space reclamation. It follows that you should
probably be using GC in general.

> Dealing with
> the scene graph case would just mean adding a new exception to our
> catch clauses.

There's a little more than that. You're going to need to capture SIGSEGV
(in UNIX) or address faults (in EROS) and redirect them back into the
C++ runtime as an exception. Certainly very doable, but the linkages may
be trickier than you expect and are highly likely to be platform
dependent.

> So I think Fresco can pass your first round of requirements, at least
> provisionally.  There are, of course, a whole lot of other issues to
> deal with, ranging from client<->server communication (Fresco uses
> CORBA -- I've been interested in EROS and E for their pleasant
> security guarantees, which CORBA entirely lacks -- but would
> Fresco-on-EROS be restricted to only local clients, for example?

For a first cut, I believe we would want to cut over to CapIDL and
restrict ourselves to local clients only. Our view of remoting is that
remote protocols should be handled by appropriate proxies on the local
machine. Since the window system is pretty sensitive code, I would
firmly reject placing that complexity in the window system at this time.

> Also, over in Fresco-land we've hardly thought about security at all
> so far.  I see you've already mentioned some of the nasty cases
> (screen scrapers, fake events, etc.); another really fun case that
> comes to mind is application embedding (cf OLE/Bonobo/KParts/OpenDoc),
> where multiple applications are actually coordinating to produce a
> single GUI.

No offense intended, but it sounds like Fresco may be due to start its
next major version. Sharing GUIS across major components of an
application is fine. Sharing across applications (the distinction being
the presence/absence of security boundaries) is verbotten.

I don't meant this to be a snide comment. One of the single biggest
issues we have had in identifying a widget set is that GUI designers
tend to operate in a "presumed collaborative" world that was inherited
from X windows. In our world, we assume that applications are actively
hostile to both the window manager and other applications.

> (In fact, application embedding raises another issue with space banks
> that perhaps someone can explain to me.  Imagine a scene graph that
> looks like
>   A -> B -> C
> where A belongs to the server (it's the root desktop node, or
> whatever), B belongs to one application, and C belongs to another
> application that's embedded in B.  If the app that owns B now shoots
> its space bank, B will disappear, orphaning C.  The way we do things
> now, the server will correctly notice that B doesn't exist, and sever
> the branch of the scene graph that was formerly rooted at B; however,
> we've now lost track of C entirely.

Destructors for B will not be called. It's not a matter of timeliness.
We have lost the authority to use that memory at all.

How would you handle this if B was a remote scene graph?

> Alternatively, the could server track
> the graph topology in reliable server memory, but that lets clients
> steal arbitrary amounts of memory again, by creating arbitrarily
> complex GUIs.  It seems, then, that a garbage collector is required.

The server certainly needs GC for this, but it may not be as bad as you
say. There are really two possibilities here:

1. C is working through B, so the C subgraph appears to the server as
indistinguishable from the B subgraph. We need not consider this
further.

2. C has a separate connection to the server (i.e. is a separate
client), and has contrived to arrange this hierarchical arrangement.
This is the case that we need to deal with.

Note that in this case we have a very easily detected situation: a
connection for which allegedly visible top level windows exist that are
unreachable in the scene graph. The server merely needs a means to
iterate over the "top level" windows of the C connection, issuing an
event for each of the form "WINDOW_UNREALIZED" and let C do what it
wills.

Note that the server must NOT disclose that the window was unrealized
because B got killed. The server has no basis for deciding that B and C
were cooperating, and must therefore make the conservative assumption
that it has no right to disclose information to C concerning the state
of B.

In fact, in order for B and C to interoperate in the way you describe,
it is incumbent on the applications to prove that they are entitled to
the relationship. In this case, this would be done by a call from client
C passing a capability to a window (or node) owned by B and requesting a
sub-node.


shap
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.