[Portland] In process? Out of process? And more...
George Staikos
staikos at kde.org
Sat Dec 10 19:31:29 EET 2005
On Friday 09 December 2005 07:07, Lars Knoll wrote:
> > I just said that because i thought problems should be fixed at the
> > lowest possible layer. Bypassing them with daemons and IPC looks a bit
> > like an overkill and should only be the last choice.
>
> I think most of us agree that unifying event loops is a good idea. It will
> however not solve every issue. One of the main problems I see with an
> in-process approach is potential stability and security issues.
We have hard evidence of this already with nspluginviewer in konqueror. Our
native plugin format, kparts, turns out to be less stable and more of a
problem than nspluginviewer in user's eyes, despite the fact that our KParts
are actually better written and more stable. Anyone can prove this to
themself by running flashplayer through valgrind and comparing to, say, a
KHTML plugin. (ok, ok, don't try kaffeine :-))
Lars knows nspluginviewer quite well. Despite some IPC design issues, it's
actually extremely robust. Many browser developers have told me privately
and publically that they would like to move to this model, but many of them
have technical issues preventing it.
> ISVs test their application with a set of libraries they link against on a
> certain desktop. an in-process approach basically means that the
> application developer can not know what kind of code might get executed in
> it's process space.
At best they can hope there is a specification to work from. Very few
opensource libraries have this.
> The other problem is interoperability between different major versions of
> the same library (Qt3 vs Qt4, Gtk2 vs a future Gtk3). These usually define
> similar sets of symbols which could lead to larger problems when loading
> them into the same address space.
This is a very big and real issue with plugins. Even worse when you start
to see libraries that clearly the people on this list haven't run into yet,
such as openldap or openssl.
> So I think that even though an out-of-process approach looks like overkill
> it's the safer road to go. On a standard desktop environment you will
> probably also not need a special daemon as the desktop has applications
> running that can just take over these functions.
I think this is only part of the answer. Here is how I see it:
We need to define a protocol in the abstract sense. We can provide a sample
implementation in plain C with no dependencies to prove that it is generic
and usable for any type of application. We can provide implementations in Qt
and GTK+ to show that it works well with existing applications on the
desktops. And we make the implementation a completely separate aspect from
the protocol. This way, we are free to implement any one or more of many
mechanisms for accessing the desktop. We can do a RUDI-style IPC based
system, a user-space runtime tool system (external executable), or native
linking.
Let's look at this from an app developer perspective.
1) I need something that is available in my language, and feels like a
first-class citizen (even if it really isn't underneath - that doesn't
matter).
2) I need something that works with my toolkit in my language.
3) I have specific goals and tasks, and if I really want something that hooks
into the desktop tightly, I am doing something very specialized and I can and
-want- to do it natively.
4) I don't want to know about implementation because that's error-prone and
not my business. Notice that this means I don't want to be reading
configuration files myself. I want to ask what I want via API and be told
the answer.
5) This should, in theory, be portable to Windows and Mac OS X too, since this
is where my migration path comes from and writing code 3 times is no fun.
Let's take some examples:
bool addMenuEntry(const char *name, const char *executable);
This is a horrible interface because it talks about implementation details,
not an abstract concept. This would not work well on any platform I know of
except perhaps if it adds a dock entry on Mac OS X, which is not even what
the API suggests it does.
bool addMenuEntry(const char *desktopFile);
This is better in some ways because the .desktop file can contain enough
information for all platforms. However it still misses a few points. For
instance, is there even a menu? On some platforms this is completely wrong
conceptually.
bool installMyApplication(struct AppInfo *myAppInfo);
This is getting very close, I think. It's task is to do the "right thing" on
whichever platform the application is running on. If it needs a .desktop
file, it builds it from the appinfo. If the app wants a launcher/dock entry,
it can suggest that via a flag in the AppInfo. There are no assumptions made
here on the Portland side OR on the app-developer side. This is what I call
a nice, robust, abstract API. And honestly, this is what we have in our own
libraries for commercial development.
At a higher level, say a GTK+ or Qt wrapper, these things could be converted
to more native structures and any existing knowledge can be auto-filled.
<tangent>
This does expose a somewhat interesting issue though. If we abstract it so
far, it makes support costs higher. I think this is quite a tangent, but
it's an extremely significant issue. If you ask me, writing the app in two
toolkits is cheaper than the tech-support and QA costs of testing it on all
those platforms, especially using this generic library. Do we have a case
where we need more management folks involved in this before we spend too much
effort on technical issues?
</tangent>
Ok, so let's consider the implementation of installMyApplication(). I imagine
it would look something like this:
installmyapp_linux.c
installmyapp_win32.c
installmyapp_macosx.c
Consider installmyapp_linux.c:
bool installMyApplication(struct AppInfo *myAppInfo) {
DesktopHandler *h = desktopHandler();
if (!h) return false;
return (h->installMyApplication)(myAppInfo);
}
DesktopHandler *desktopHandler() {
if (globalHandlerObject) return globalHandlerObject;
Desktop d = detectDesktop();
globalHandlerObject = loadHandlerForDesktop(d);
return globalHandlerObject;
}
DesktopHandler* could have fields indicating app preference for (or
prohibiting the library from using) in-process, out-of-process, etc, but
would typically take the best available option.
I think this gives us maximal flexibility for later. We can break major tasks
down to give more finegrained (with caveats) access to the system, we can
change implementations, and more. The only exposure we have is in any global
types we expose.
It also allows us to get to a proof-of-concept very rapidly. We can implement
a few specific tasks and use a backend written in the most rapid manner.
Any thoughts?
--
George Staikos
KDE Developer http://www.kde.org/
Staikos Computing Services Inc. http://www.staikos.net/
More information about the Portland
mailing list