Thread overview | |||||
---|---|---|---|---|---|
|
September 10, 2006 Child thread blocks main thread | ||||
---|---|---|---|---|
| ||||
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 |
September 10, 2006 Re: Child thread blocks main thread | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jona Joachim Attachments: | Hi,
I haven't looked at your code below, but I thought you might find another example of the same thing useful, so, attached is a little process/pipe library I wrote.
Regan
On Sun, 10 Sep 2006 18:12:54 +0200, Jona Joachim <jaj13@web.de> wrote:
> 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
|
September 11, 2006 Re: Child thread blocks main thread | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | On Mon, 11 Sep 2006 10:54:48 +1200, Regan Heath wrote:
> Hi,
>
> I haven't looked at your code below, but I thought you might find another example of the same thing useful, so, attached is a little process/pipe library I wrote.
Thanks! I'll try it out once I get a chance!
I still don't know if it is normal that the syscall to system()
blocks the entire process rather than the thread but if your code works
I'm willing to take it :)
Jona
|
Copyright © 1999-2021 by the D Language Foundation