Plan 9 and Inferno at the Google Summer of Code

FIREFOX PLUGIN UPDATE

Inferno Plugin update

I have had many problems with the memory management due to the fact that the plugin is loaded as a shared library. This implies that when the inferno code calls to malloc/free/realloc it calls the malloc/free/realloc functions from libc instead the malloc/free/realloc functions defined in alloc.c. This happens because the plugin is a shared library, and when the inferno code calls malloc, it finds the libc malloc before the inferno’s malloc redefinition, idem with free and realloc.

In order to solve this issue I renamed malloc, free and realloc from alloc.c to imalloc, ifree and irealloc, writing the preprocessor directives in fns.h:

#define malloc(s) imalloc(s)
#define free(l) ifree(l)
#define realloc(v,s) irealloc(v,s)

But this result in another problem, there are calls to ifree where its argument is not a memory reference reserved by imalloc, and when it tries to free this memory an “not in pools” error ocurrs. In order to find where there is ifree calls to free memory reserved by libc malloc instead inferno imalloc I have used the ElectricFence library (thanks Chris), putting it in the LD_PRELOAD path so any call to malloc/free will call the malloc/free of EF, this way I have found (after many problems) the ifree call culprit of the problem. This call was inside the kstrdup function, the above mentioned function is that:

void
kstrdup(char **p, char *s)
{
    int n;
    char *t, *prev;
    n = strlen(s)+1;
    t = kmalloc(n);

    if(t == nil)
        panic("kstrdup: no memory");

    memmove(t, s, n);   
    prev = *p;
    *p = t;

    free(prev);
}

You can notice that at the end of the kstrdup function it calls to free(prev) (that finally is ifree(prev)), where ‘prev’ contains the last content of the reference that now references to the string copy ’s'. The problems comes when the above mentioned pointer has not been initialized and does not contain memory reserved by imalloc but libc malloc. This happens with the string ‘eve’ which is initialized in main() (main.c) by calling strdup (libc), internally strdup calls libc malloc, then eve’s memory has been reserved by glib malloc not inferno’s imalloc, nevertheless, in libinit() eve’s content is changed by calling kstrdup(eve,“newstring”), and when it tries to free the previous content of eve it try to free it calling ifree (when it was reserved by libc’s malloc not inferno malloc).

To solve this issue I have wrote a strdup redefinition named istrdup that does the same that standard strdup but calling imalloc instead libc’s malloc.

In addition, inferno code calls to sbrk to get for memory from the host OS to allow that inferno manages this memory. To be able to reserve memory acting as a plugin it is necessary to to call to NPN_MemAlloc() (Mozilla NPAPI) so I have added a redefinition of sbrk named isbrk that gives memory to inferno using Mozilla’s API. In order to let the plugin use istrdup/isbrk instead of strdup/sbrk of libc I have added other directives to fns.h:

#define strdup(s) istrdup(s) 
#define sbrk(s) isbrk(s)

With this the problem of the memory management seems to be solved (for the present).

Process Management

Mozilla Firefox API for Plugins does not offer functions to create and manage process or threads, so it is possible to use directly the same calls for the process creation in Linux. Nowadays I have tried to create processes with kproc and it seems that everything is alright.

Nowadays Status

The problem that I have now is with the calls to ksetenv, when ksetenv is called in emuinit Firefox crash, and the only thing that says is “Firefox: Unknown error 2988458393”, I have traced the calls and it seems that ksetenv (env.c) calls to namec() (chan.c), the flow enters the switch(amode) statement and go to the branch ‘Acreate’ where it calls to walk() and gives the error.

If I comment the ksetenv call, then emuinit runs without problems, but emuinit is called from libinit by:

   executeonnewstack(tos, emuinit, imod);

But after this statement nothing statement is executed, so the ‘for’ iteration of the end of emuinit will keep the control of the main plugin process, and then the plugin does not respond neither offer the NPP functins that Mozilla needs. Then the plugin does not respond to the browser requests and finally crash. The plugin must offer many NPP functions in order to comunicate with Firefox, one of these function is NPP_Init where the plugin initialices and where I have added the call to ipluginmain() (firefox-os.c) that is the entry point to inferno from the plugin.

Maybe a possible solution to this is to create a new independent process where execute ipluginmain while the main process remains running and receiving browser requests…

Planning:

I have this aims:

Memory initialization semms to be solved, process initialization seems to work but it could cause problems, emuinit does not load right due to the ksetenv problem, when I solve this I hope to have an initialized and running inferno.

The next steps are:

Console: Paint the console (emu running) -> On August 14 Hello Worlds: execute a simple “hello world” within the console -> On August 15 Text Input by keyboard to feed the console -> On August 17 Paint graphics and handle mouse events -> On August 22 Clean the code -> On August 25

Please any comments will be welcome.

Thanks.