This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Problem with Cygwin's fdopen and Windows handles


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]