run process with popen() - Linux

This is a discussion on run process with popen() - Linux ; Hi, I start a process like following: | FILE *process; | process = popen("command...", "r"); If I want to get stdout (for example into char buffer variable) then I have to do following: | cReadLine rl; | char *buffer = ...

+ Reply to Thread
Results 1 to 9 of 9

Thread: run process with popen()

  1. run process with popen()

    Hi,
    I start a process like following:
    | FILE *process;
    | process = popen("command...", "r");

    If I want to get stdout (for example into char buffer variable) then I have
    to do following:
    | cReadLine rl;
    | char *buffer = NULL;
    | if(process)
    | asprintf(&buffer, rl.Read(process));

    But my questions...
    -if a process end then the result of "if(process)" would be false, am I
    right?
    -how do I know when to get stdout? I mean how do I know that a process did
    output somewhat to stdout? Or should I really run a while-loop like:
    | while (process)
    | asprintf(&buffer, rl.Read(process));

    I think it's a bad idea since such loop would make cpu busy.

    In the past I was using QT4-Framework. It has nice signal/slot feature so I
    easily can write a slot for reading stdout and connect a signal (if a
    process (class QProcess) write somewhat to stdout) to this slot. So I
    didn't need do a while like above. Is there a aquivalent of QProcess in
    STL?

    cu Floh

  2. Re: run process with popen()

    On Dec 6, 2:52 am, Florian Erfurth wrote:
    > Hi,
    > I start a process like following:
    > | FILE *process;
    > | process = popen("command...", "r");
    >
    > If I want to get stdout (for example into char buffer variable) then I have
    > to do following:
    > | cReadLine rl;
    > | char *buffer = NULL;
    > | if(process)
    > | asprintf(&buffer, rl.Read(process));
    >
    > But my questions...
    > -if a process end then the result of "if(process)" would be false, am I
    > right?


    No. You stored the result of 'popen' in 'process' and until you change
    its value, it will continue to contain the same value. The 'popen'
    function only returns NULL if it was unable to create the process.

    > -how do I know when to get stdout? I mean how do I know that a process did
    > output somewhat to stdout? Or should I really run a while-loop like:
    > | while (process)
    > | asprintf(&buffer, rl.Read(process));
    >
    > I think it's a bad idea since such loop would make cpu busy.


    It will make the CPU busy because even after the process no longer
    exists, you still keep calling 'rl.Read' in an infinite loop. In other
    words, you have a bug. You loop is looping on the return value of
    'popen' when it should be looping on the return value of 'Read'. If
    the read fails, you want to break out of the loop, not if you were
    unable to create the process in the first place.

    > In the past I was using QT4-Framework. It has nice signal/slot feature so I
    > easily can write a slot for reading stdout and connect a signal (if a
    > process (class QProcess) write somewhat to stdout) to this slot. So I
    > didn't need do a while like above. Is there a aquivalent of QProcess in
    > STL?


    When the process dies, the connection to it will die too.

    You have a common C misunderstanding. The language does not manage the
    validity and lifetime of pointers, you do. For example:

    FILE *f=popen("ls -l", "r");
    pclose(f);
    if(f) printf("Odd, I closed the process\n");

    At this point, the value of 'f' has not changed. It still points to
    the the memory that the FILE structure was in before and now is not
    in. If you want 'if (f)' to fail, you must set 'f' to NULL yourself.
    You will get the message 'Odd, I closed the process' so long as the
    process could be created. If the process could not be created, the
    result of the 'pclose' is undefined.

    But this is correct:

    FILE *f=popen("ls -l", "r);
    if(f!=NULL)
    {
    /* we can read from the process now if we want to */
    pclose(f);
    f=NULL;
    }
    /* now f is NULL no matter what */

    Normally, C programmers do not bother setting pointers to NULL, they
    just stop using them. There are cases where it makes sense though, for
    example, with code like:

    Thing *pointer=NULL;

    if(pointer!=NULL) pointer=MakeNewThing();
    /* ... */
    if(OperationFails(pointer))
    {
    RemoveThing(pointer);
    pointer=NULL;
    }

    DS

  3. Re: run process with popen()

    David Schwartz wrote:

    > On Dec 6, 2:52 am, Florian Erfurth wrote:
    >> Hi,
    >> I start a process like following:
    >> | FILE *process;
    >> | process = popen("command...", "r");
    >>
    >> If I want to get stdout (for example into char buffer variable) then I
    >> have to do following:
    >> | cReadLine rl;
    >> | char *buffer = NULL;
    >> | if(process)
    >> | asprintf(&buffer, rl.Read(process));
    >>
    >> But my questions...
    >> -if a process end then the result of "if(process)" would be false, am I
    >> right?

    >
    > No. You stored the result of 'popen' in 'process' and until you change
    > its value, it will continue to contain the same value. The 'popen'
    > function only returns NULL if it was unable to create the process.

    Oh, you're right!

    >> -how do I know when to get stdout? I mean how do I know that a process
    >> did output somewhat to stdout? Or should I really run a while-loop like:
    >> | while (process)
    >> | asprintf(&buffer, rl.Read(process));
    >>
    >> I think it's a bad idea since such loop would make cpu busy.

    >
    > It will make the CPU busy because even after the process no longer
    > exists, you still keep calling 'rl.Read' in an infinite loop. In other
    > words, you have a bug. You loop is looping on the return value of
    > 'popen' when it should be looping on the return value of 'Read'. If
    > the read fails, you want to break out of the loop, not if you were
    > unable to create the process in the first place.

    That means I should do like following:
    | asprintf(&buffer, rl.Read(process));
    | while(buffer)
    | DoSomewhat_with_buffer();
    | asprintf(&buffer, rl.Read(process));

    But... a process, which I want to run needs about 1-2minutes and the output
    happens about every 10-15 seconds. That's why I don't like such while-loop
    since it makes cpu busy. I would like to run read-command only if a process
    did put somewhat into stdout. :/

    > When the process dies, the connection to it will die too.

    Hm... what do you mean?

    > You have a common C misunderstanding. The language does not manage the
    > validity and lifetime of pointers, you do. For example:
    >
    > FILE *f=popen("ls -l", "r");
    > pclose(f);
    > if(f) printf("Odd, I closed the process\n");
    >
    > At this point, the value of 'f' has not changed. It still points to
    > the the memory that the FILE structure was in before and now is not
    > in. If you want 'if (f)' to fail, you must set 'f' to NULL yourself.
    > You will get the message 'Odd, I closed the process' so long as the
    > process could be created. If the process could not be created, the
    > result of the 'pclose' is undefined.

    Same like above you're right. But how the hell do I know when does a process
    end so I can do pclose(process)?

    cu Floh

  4. Re: run process with popen()

    On a sunny day (Thu, 06 Dec 2007 11:52:19 +0100) it happened Florian Erfurth
    wrote in
    <4757d57f$0$17540$9b4e6d93@newsspool4.arcor-online.net>:

    >Hi,
    >I start a process like following:
    >| FILE *process;
    >| process = popen("command...", "r");
    >
    >If I want to get stdout (for example into char buffer variable) then I have
    >to do following:
    >| cReadLine rl;
    >| char *buffer = NULL;
    >| if(process)
    >| asprintf(&buffer, rl.Read(process));
    >
    >But my questions...
    >-if a process end then the result of "if(process)" would be false, am I
    >right?
    >-how do I know when to get stdout? I mean how do I know that a process did
    >output somewhat to stdout? Or should I really run a while-loop like:
    >| while (process)
    >| asprintf(&buffer, rl.Read(process));
    >


    How about, if process, using getc() or read() until you see EOF?
    Then you still have to close 'process'.

  5. Re: run process with popen()

    Jan Panteltje wrote:

    > On a sunny day (Thu, 06 Dec 2007 11:52:19 +0100) it happened Florian

    Hm... here is cloudy and no sun. O_o *g*

    > Erfurth wrote in
    >
    >>But my questions...
    >>-if a process end then the result of "if(process)" would be false, am I
    >>right?
    >>-how do I know when to get stdout? I mean how do I know that a process did
    >>output somewhat to stdout? Or should I really run a while-loop like:
    >>| while (process)
    >>| asprintf(&buffer, rl.Read(process));

    >
    > How about, if process, using getc() or read() until you see EOF?
    > Then you still have to close 'process'.

    Hm... that would answer my question:
    "How do I know, when does a process end?"

    But there is still anoter question:
    "When should I read stdout? How do I know, when did process put something
    into stdout?"

    Thank you very much!
    cu Floh

  6. Re: run process with popen()

    On a sunny day (12 Sep 2006 02:52:53 -0700) it happened "Himanshu Chauhan"
    wrote in
    <1158054773.592022.154770@b28g2000cwb.googlegroups. com>:

    >Dear all,
    >
    >Does linux has any service through which the user application can be
    >notified about the newly mounted cdrom or filesystem? Any callback
    >routines? Or the only option is a watchdog type stuff?
    >
    >Thanks,
    >
    >Regards


    Well, it seems it waits! (likely for a CR or something).
    Try this, both for 'ls -rtl' and for 'cat /dev/random'
    cat /dev/random will only output when it has gathered enough stuff,
    run a couple of times, and wait a long time for output on some occasions.

    #include
    #include

    int main(int argc, char **argv)
    {
    int a;
    FILE *pptr;

    //pptr = popen("ls -rtl", "r");
    pptr = popen("cat /dev/random", "r");
    if(!pptr)
    {
    fprintf(stderr, "test4: could not open ls -rtl for read, aborting.\n");

    exit(1);
    }

    while(1)
    {
    a = fgetc(pptr);
    if(a == EOF)
    {
    fprintf(stderr, "test4: EOF detected.\n");

    pclose(pptr);

    exit(0);
    }

    fprintf(stdout, "%0x2", a);
    }


    fprintf(stderr, "WAS HERE, OOOPS.\n");

    exit(0);
    } /* end function main */



  7. Re: run process with popen()

    Florian Erfurth wrote:

    > But my questions...
    > -if a process end then the result of "if(process)" would be false, am I
    > right?
    > -how do I know when to get stdout? I mean how do I know that a process did
    > output somewhat to stdout? Or should I really run a while-loop like:


    I did resolve my problem as following:
    process.c
    | #include "tools.h"
    |
    | int main()
    | {
    | FILE *process;
    | process = popen("ls -la", "r");
    |
    | cReadLine rl;
    | char *buffer;
    |
    | buffer = rl.Read(process);
    | while(buffer)
    | {
    | printf("\033[0;93m Output: %s \033[0m\n", buffer);
    | buffer = rl.Read(process);
    | }
    | pclose(process);
    | printf("\033[0;41m Prozess Beendet! \033[0m\n");
    | }

    tools.c
    | #include
    | #include "tools.h"
    |
    | cReadLine::cReadLine(void)
    | {
    | size = 0;
    | buffer = NULL;
    | }
    |
    | cReadLine::~cReadLine()
    | {
    | free(buffer);
    | }
    |
    | char *cReadLine::Read(FILE *f)
    | {
    | int n = getline(&buffer, &size, f);
    | if (n > 0) {
    | n--;
    | if (buffer[n] == '\n') {
    | buffer[n] = 0;
    | if (n > 0) {
    | n--;
    | if (buffer[n] == '\r')
    | buffer[n] = 0;
    | }
    | }
    | return buffer;
    | }
    | return NULL;
    | }

    tools.h
    | #ifndef __TOOLS_H
    | #define __TOOLS_H
    |
    | #include
    |
    | class cReadLine
    | {
    | private:
    | size_t size;
    | char *buffer;
    | public:
    | cReadLine(void);
    | ~cReadLine();
    | char *Read(FILE *f);
    | };
    |
    | #endif

    The code from tools.c and tools.h are parts of vdr-1.4 code which is under
    GPLv2.

    Opinion about process.c? Is it ok so?

    cu Floh

  8. Re: run process with popen()

    On Dec 6, 5:41 am, Florian Erfurth wrote:

    > Opinion about process.c? Is it ok so?


    Where is the buffer allocated?

    DS

  9. Re: run process with popen()

    On Dec 6, 5:41 am, Florian Erfurth wrote:

    > Opinion about process.c? Is it ok so?


    You have memory leaks. Read should do this:

    if(buffer!=NULL) { free(buffer); buffer=NULL; }
    getline(...)

    Otherwise, only the last line is ever freed.

    Ignore the other reply from me. This one is correct, that one is not.

    DS


+ Reply to Thread