#3231: Permission denied error with runProcess/openFile
---------------------------------+------------------------------------------
Reporter: NeilMitchell | Owner: simonmar
Type: bug | Status: closed
Priority: normal | Milestone: 6.12.1
Component: Runtime System | Version: 6.10.4
Severity: normal | Resolution: invalid
Keywords: | Difficulty: Unknown
Testcase: | Os: Windows
Architecture: Unknown/Multiple |
---------------------------------+------------------------------------------
Comment (by yugr):
Thanks, Simon.
Now goes the tricky part. Below you will find the text of {{{a.exe}}}. It
is a simple WinAPI program which starts a few processes, sleeps a bit,
terminates them and exits. With this program I receive the errors which I
mentioned above:
{{{bug.exe: mytempfile.txt: openFile: permission denied (Permission
denied)}}}
or if I remove if-then-else
{{{bug.exe: DeleteFile}}}
Here is my idea of what is happening. As you may know
{{{TerminateProcess}}} does not necesseraly terminate the process
immediatelly (or even terminate it at all). This is especially common if
process holds some system resource (pipe handle in this case). So when
main process exits some children may still be alive and keep handles for
stdout and stderr open for writing (for a few milliseconds). This causes
errors when I try to read file in Haskell (via {{{B.readFile}}}) or even
if I try to remove it (via {{{removeFile}}}).
Now the question - should this problem (error when trying to read
stdout/stderr of multiprocess program) be considered a feature or a bug?
If it is a feature - can I handle it from inside Haskell (e.g. imagine
that I do not have access to source of {{{a.exe}}})?
Here is the program text. Error occurs both when compiled with Cygwin's
gcc (just {{{gcc tmp.c}}}) and with Visual Studio's {{{cl}}}. If someone
needs a Makefile or M$VS project - let me know and I will send you one.
{{{
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define PIPE_NAME "\\\\.\\pipe\\MySmallPipe"
#define PIPE_BUF_SIZE 10
#define TIMEOUT 1000
#define NCLIENTS 30
int main(int argc, char *argv[]) {
if( 1 == argc ) {
//Caller
struct {
HANDLE hProcess;
HANDLE hPipe;
OVERLAPPED ov;
} data[NCLIENTS];
//Start clients
int i;
for(i = 0; i < NCLIENTS; ++i) {
fprintf(stderr, "Starting %d\n", i);
data[i].hPipe = CreateNamedPipe(
PIPE_NAME,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
PIPE_WAIT,
100,
PIPE_BUF_SIZE,
PIPE_BUF_SIZE,
TIMEOUT,
0
);
assert(INVALID_HANDLE_VALUE != data[i].hPipe);
STARTUPINFO si;
memset(&si, 0, sizeof (STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
BOOL res = CreateProcess(0, strdup("a.exe 1"), 0,
0, TRUE, 0, 0, 0, &si, &pi);
assert(res);
data[i].hProcess = pi.hProcess;
ConnectNamedPipe(data[i].hPipe, &data[i].ov);
} //i
fprintf(stderr, "Delay\n");
Sleep(TIMEOUT);
//Kill clients
for(i = 0; i < NCLIENTS; ++i) {
fprintf(stderr, "Terminating %d\n", i);
BOOL res = TerminateProcess(data[i].hProcess, 0);
DisconnectNamedPipe(data[i].hPipe);
CloseHandle(data[i].hPipe);
} //i
} else {
//Callee
fprintf(stderr, "Started\n");
BOOL res = WaitNamedPipe(PIPE_NAME, TIMEOUT);
assert(res);
HANDLE hPipe = CreateFile(
PIPE_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0
);
//Sleep forever
char buf[PIPE_BUF_SIZE];
DWORD n;
res = ReadFile(
hPipe,
buf,
PIPE_BUF_SIZE,
&n,
0
);
}
return 0;
}
}}}
Best regards,
Yuri
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/3231#comment:33>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs