X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=-1.0 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED,SPF_HELO_PASS,T_RP_MATCHES_RCVD,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org To: cygwin AT cygwin DOT com From: Juanjo Subject: Problem with Cygwin's fdopen and Windows handles Date: Sun, 29 May 2011 11:35:03 +0000 (UTC) Lines: 137 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit User-Agent: Loom/3.14 (http://gmane.org/) X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com 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 #include #include #include #include #include /* For cygwin_attach_handle_to_fd() */ #include 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