Child thread blocks main thread

Jona Joachim jaj13 at web.de
Sun Sep 10 09:12:54 PDT 2006


Hi!
I have a problem concerning threads.

What I want to do is redirect the output of a shell command to a text
widget.

Here is my approach:
- create a thread that connects stdout to a named pipe an calls system()
to run the command. The output of the command is then redirected to the
pipe.
- create another thread that reads the pipe an writes the output to the
text widget.
- the main thread keeps running so that the application doesn't block and
offers the ability to cancel the subprocesses.

The problem is that writing to a pipe is blocking until the pipe gets
read. I thought that the write thread would get blocked until the read
thread reads the pipe but instead the entire program blocks until the pipe
is read. Why doesn't the main thread continue to run when the write thread
blocks?

Here is my code:

import std.stdio;
import std.thread;

extern(C) int dup(int);
extern(C) int dup2(int, int);
extern (C) int mkfifo(char*, int);
extern(C) int system(char*);
extern(C) int close(int);

class writeToFifo : Thread
{
  private:
    char[] _cmd;
    int _stdout_old;
    fpos_t _pos;

  public:
    this(char[] command, char[] pipe)
    {
      _cmd = command;

      fflush(stdout);
      fgetpos(stdout, &_pos);
      _stdout_old = dup(fileno(stdout));

      mkfifo(pipe, 0600);
      stdout = freopen(pipe, "w", stdout);

      super();
    }

    ~this()
    {
      fflush(stdout);
      dup2(_stdout_old, fileno(stdout));
      close(_stdout_old);
      clearerr(stdout);
      fsetpos(stdout, &_pos);        /* for C9X */
    }

    int run()
    {
      system(_cmd);
      return 0;
    }
}

class readFromFifo : Thread
{
  private:
    _iobuf* _pipe;
  
  public:
    this(char[] pipe)
    {
      _pipe = fopen(pipe, "r");

      super();
    }

    ~this()
    {
      fclose(_pipe);
    }

    int run()
    {
      char buffer;

      while(!feof(_pipe) && !ferror(_pipe))
      {
        fprintf(stderr, "%s", fgetc(_pipe));
      }

      return 0;
    }
}

int main(char[][] argv)
{
  writeToFifo writeT = new writeToFifo("ls -l", "/tmp/foopipe");
  writeT.start(); /* this blocks so the rest is never executed */
  
  readFromFifo readT = new readFromFifo("/tmp/foopipe");
  readT.start();

  writeT.wait();
  
  return 0;
}


Best regards,
Jona



More information about the Digitalmars-d-learn mailing list