Actually there are two different problems related to my implementation of a
Common Lisp environment, ecl (http://ecls.sf.net)

The first one has to do with fork() not working, due to the fact that ECL
injects DLLs using dlopen() and they are then improperly loaded. I have seen in
the mailing list that this is a known problem with no solution so far.

To cope with that problem I had to resort to CreateProcess, a Windows routine
that allows us to redirect the input/output/error channels of a process as
needed. The problem I have is that the C streams that result from the Windows
handle can only be read with read() and not with fread(). This is a problem
because the ECL environment needs buffered I/O, with locking and so on, and we
rely on C streams for that.

I attach a small test program that segfaults when using fread() on the stream
created with fdopen(). notice that read() works.

Any help is really welcome and appreciated.

Juanjo


/* -*- mode: c; c-basic-offset: 8 -*- */
/*
    unixsys.s  -- Unix shell interface.
*/
/*
    Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
    Copyright (c) 1990, Giuseppe Attardi.
    Copyright (c) 2001, Juan Jose Garcia Ripoll.

    ECL is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    See file '../Copyright' for full details.
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/cygwin.h> /* For cygwin_attach_handle_to_fd() */
#include <windows.h>

int main()
{
        BOOL ok;
        STARTUPINFO st_info;
        PROCESS_INFORMATION pr_info;
        HANDLE child_stdout, child_stdin, child_stderr;
        HANDLE current = GetCurrentProcess();
        SECURITY_ATTRIBUTES attr;
        int parent_read;

        ZeroMemory(&attr, sizeof(attr));
        attr.nLength = sizeof(attr);
        attr.lpSecurityDescriptor = NULL;
        attr.bInheritHandle = TRUE;

        /* Creates a pipe that we can write to and the
           child reads from. We duplicate one extreme of the
           pipe so that the child does not inherit it. */
        child_stdin = NULL;
        child_stderr = NULL;
        {
                HANDLE tmp;
                ok = CreatePipe(&tmp, &child_stdout, &attr, 0);
                if (ok) {
                        ok = DuplicateHandle(current, tmp, current,
                                             &tmp, 0, FALSE,
                                             DUPLICATE_CLOSE_SOURCE |
                                             DUPLICATE_SAME_ACCESS);
                        if (ok) {
                                parent_read =
                                        cygwin_attach_handle_to_fd
                                        (0, -1, tmp, S_IRWXU, GENERIC_READ);
                                printf("parent_read=%d\n",parent_read);
                                if (parent_read < 0)
                                        printf("open_osfhandle failed\n");
                        }
                }
        }

        /* Launches the process
         */
        ZeroMemory(&st_info, sizeof(st_info));
        st_info.cb = sizeof(st_info);
        st_info.lpTitle = NULL; /* No window title, just exec name */
        st_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; /* 
Specify
std{in,out,err} */
        st_info.wShowWindow = SW_HIDE;
        st_info.hStdInput = child_stdin;
        st_info.hStdOutput = child_stdout;
        st_info.hStdError = child_stderr;
        ZeroMemory(&pr_info, sizeof(pr_info));
        ok = CreateProcess(NULL, "c:\\cygwin\\bin\\echo.exe \"--version\"",
                           NULL, NULL, /* lpProcess/ThreadAttributes */
                           TRUE, /* Inherit handles (for files) */
                           /*CREATE_NEW_CONSOLE |*/
                           0 /*(input == Ct || output == Ct || error == Ct ? 0 
: CREATE_NO_WINDOW)*/,
                           NULL, /* Inherit environment */
                           NULL, /* Current directory */
                           &st_info, /* Startup info */
                           &pr_info); /* Process info */
        if (!ok) {
                char *message;
                printf("ABORT\n");
                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
                              FORMAT_MESSAGE_ALLOCATE_BUFFER,
                              0, GetLastError(), 0, (void*)&message, 0, NULL);
                printf("%s\n", message);
                LocalFree(message);
                return 1;
        }
        /* Now reads. No problem with C read */
        {
                char c[100];
                int n = read(parent_read, c, 10);
                c[n] = 0;
                printf("c[%d] = %s\n", n, c);
        }
        /* But this segfaults */
        {
                FILE *f= fdopen(parent_read, "rb");
                char c[100];
                int n;
                printf("fp=%p\n", f);
                n = fread(c, 4, 1, f);
                c[n] = 0;
                printf("c[%d] = %s\n", n, c);
        }
        return 0;
}



--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to