The problem you just found is intimately related to the other one. ECL
uses a garbage collector, evaluation environments and other stuff that
has to be created *for each* thread where you want to execute or
evaluate Common Lisp code. In the simple modification you made the
routine new_Command1 just evaluated a lisp form in a thread that was
simply not prepared for it.

The solution is to construct one or more Common Lisp slave threads
that are responsible for executing code and communicating the
appropriate output to the master threads, which may be dynamically
created and destroyed by the GUI library.

Below is  cut & paste of some code I tested with your application. It
works fine, except for the problem with quitting, which leaves the 4D
environment in some kind of locked status. Debugging does not offer
much information: all the active threads are from 4D and I do not have
the sources of it.

typedef struct {
        int pipe[2];
        void *message;
        int integer;
} comm_t;

void
comm_open(comm_t *c)
{
        pipe(c->pipe);
}

void
comm_close(comm_t *c)
{
        close(c->pipe[0]);
        close(c->pipe[1]);
}

void *
comm_read(comm_t *c)
{
        char b;
        printf("Reading from pipe from %x\n", (int)pthread_self());
        if (read(c->pipe[0], &b, sizeof(b)) < 0 || b != 0x13)
                return NULL;
        return c->message;
}

void
comm_write(comm_t *c, void *message)
{
        static const char b[1] = { 0x13 };
        c->message = message;
        printf("Writing to pipe from %x\n", (int)pthread_self());
        write(c->pipe[1], b, sizeof(*b));
}

int
comm_read_int(comm_t *c)
{
        comm_read(c);
        return c->integer;
}

void
comm_write_int(comm_t *c, int i)
{
        c->integer = i;
        comm_write(c, &c->integer);
}

#define EMBED_ECL
#ifdef EMBED_ECL

static pthread_t ecl_thread;
static comm_t slave_pipe[1];
static comm_t master_pipe[1];

static void *
ecl_thread_entry(void *aux)
{
        int argc = 1;
    char * argv[256];
        cl_env_ptr env;
    argv[0] = "";    // cl_boot(argc, argv);
        printf("Entering slave thread\n");
        GC_register_my_thread(argv);

        // This fixes a wrong initialization of GC_stackbottom
        // that only happens in OS X
        GC_stackbottom = (void*)(argv+255);

        ecl_set_option(ECL_OPT_TRAP_SIGSEGV, 0);
        ecl_set_option(ECL_OPT_TRAP_SIGFPE, 0);
        ecl_set_option(ECL_OPT_TRAP_SIGSEGV, 0);
        ecl_set_option(ECL_OPT_TRAP_SIGINT, 0);
        ecl_set_option(ECL_OPT_TRAP_SIGILL, 0);
        ecl_set_option(ECL_OPT_TRAP_SIGBUS, 0);
        ecl_set_option(ECL_OPT_TRAP_INTERRUPT_SIGNAL, 0);
        ecl_set_option(ECL_OPT_SIGNAL_HANDLING_THREAD, 0);
        ecl_set_option(ECL_OPT_INCREMENTAL_GC, 0);
        
        cl_boot(argc,argv);
        env = ecl_process_env();

        // Lisp command loop
        CL_CATCH_ALL_BEGIN(env) {
                do {
                        char *command = (char *)comm_read(slave_pipe);
                        if (command) {
                                cl_object c = c_string_to_object(command);
                                printf("%s\n", command);
                                cl_print(1,c);
                                comm_write_int(master_pipe, ecl_length(c));
                        } else {
                                break;
                        }
                } while (1);
        } CL_CATCH_ALL_END;

        // Shut down ECL and remove links with garbage collector
        cl_shutdown();
        GC_unregister_my_thread();
        printf("Exited slave thread\n");
        return NULL;
}

#endif // EMBED_ECL

void InitPlugin()
{
#undef pthread_create
#ifdef EMBED_ECL
        printf("Init thread: %p\n", (void*)pthread_self());
        comm_open(slave_pipe);
        comm_open(master_pipe);
        pthread_create(&ecl_thread, NULL, ecl_thread_entry, NULL);
        printf("Finished initialization\n");
#endif
}

void DeinitPlugin()
{
#ifdef EMBED_ECL
        comm_write(slave_pipe, NULL);
        comm_close(slave_pipe);
        comm_close(master_pipe);
        printf("DeinitPlugin() exited\n");
#endif
}

--
Instituto de FĂ­sica Fundamental, CSIC
c/ Serrano, 113b, Madrid 28006 (Spain)
http://juanjose.garciaripoll.googlepages.com

------------------------------------------------------------------------------
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share
of $1 Million in cash or HP Products. Visit us here for more details:
http://p.sf.net/sfu/dev2dev-palm
_______________________________________________
Ecls-list mailing list
Ecls-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ecls-list

Reply via email to