#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

Reply via email to