WWW

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • returning page before long process is finished using C

    7 answers - 1658 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    I looked up the faq and found this, but found it very vague.
    3.8: Can I launch a long process and return a page before it's
    finished?
    [UNIX]
    You have to fork/spawn the long-running process.
    The important thing to remember is to close all its file descriptors;
    otherwise nothing will be returned to the browser until it's finished.
    The standard trick to accomplish this is redirection to/from /dev/null:
    "long_process < /dev/null /dev/null 2>&1 &"
    print HTML page as usual
    (don't take "exec" as literal in anything but a shell script - in C,
    Perl, etc use fork+exec or system() :-)
    i looked up fork and exec and found that there are many different exec*
    calls so I am clueless on how to use this. Can anyone give me an
    example or point me on how to fork a process using C? The cgi process
    could take anywhere from 5 secs or a day depending on the input data so
    I want to have the current webpage, where the form is, forward
    immediately to a page having a message display, "your data is currently
    being processed and will be available at http:// once complete."
    After the data is processed, this page will be refreshed to the
    resulting page that the cgi processed. Here is a newbie attempt at
    this.
    pid = fork();
    if (pid == 1){
    // call the exec here?
    printf("Location: %s\n\n", szURL); // this is the page
    i want to display right away
    _exit(0);
    }
    else if (pid < 0) {
    // print some error message that couldn't fork
    _exit(0);
    }
    else {
    // do the long processing here?
    }
    Any help is appreciated. Thanks.
  • No.1 | | 691 bytes | |

    vduber6er wrote:

    pid = fork();
    if (pid == 1){

    ITYM 0. That means you're in the child process, which is where
    you want to do the processing (close your filedescriptors
    and/or detach your session first).

    // call the exec here?
    printf("Location: %s\n\n", szURL); // this is the page
    i want to display right away
    _exit(0);

    Why _exit rather than exit() ?
    }
    else if (pid < 0) {
    // print some error message that couldn't fork
    _exit(0);
    }
    else {
    // do the long processing here?

    No, this is the parent process, which should return an immediate
    page to the user.

    }

    Any help is appreciated. Thanks.
  • No.2 | | 1218 bytes | |

    Here is a perl example that explains how to use fork and exec together
    with nearly failproof error checking:

    use Errno qw(EAGAIN);
    FRK:
    if($pid = fork) {
    #you are now the parent process
    #this is where you would want to print out the html page
    } elsif(defined $pid) {
    #this is the child process
    #this is where you would exec the longer process

    exec('longer_process.pl') or die "Could not exec process";
    } elsif($! == EAGAIN) {
    #an error occured while trying to fork a new process
    #this is a recoverable error so wait a little then try again
    sleep 5;
    redo FRK;
    } else {
    #an error occured while trying to fork that is not recoverable
    die "could not fork a process";
    }
    }

    A couple of notes:
    1. I didn't test this code.
    2. If the user were to close the browser window before the second
    process is done, the second process will terminate as well. to get
    around this you might want to use wait(); in the code for the parent
    process. You might do something like this:
    #print your HTML page
    print "<br>Processing <br>";
    wait($pid);
    print "<br>Done Processing<br>";

    hope this helps
  • No.3 | | 263 bytes | |

    Ahh sorry forgot something in my last post in C the process is
    very similar find a good C reference book that explains how to use
    fork and exec properly the book is excelent (mine is at
    home) I don't remember how anymore been doing perl to long now.
  • No.4 | | 345 bytes | |

    Another question. Could I do this all within the long process? All the
    code (that creates the cgi and has the long data processing) is in
    mycode.c. Could I put the, printing html, fork and exec stuff in
    mycode.c or does it have to be in some other file that would exec the
    cgi file that mycode.c generates? Hope I make sense. Thanks.
  • No.5 | | 1009 bytes | |

    definitly, just replace exec('long_process.pl'); with the code for the
    long process.

    just another note
    This is how the fork command works:

    if fork succeeds it returns the process id ($pid) of the child
    process to the parent process and 0 to the child process. if it fails
    it returns undef. File descriptors are shares between processes
    but everything else is not.

    It's good proctice to remember to end a child node with exit(); This
    way your child node doesn't inadvertantly execute code that is only
    ment for the parent.
    Always remember to wait(); in the parent node before closing out. If
    you don't do this, your child process will become a zombie process.

    Also, be carefull using fork() on a windows system, there serious
    performance issues with this. Windows has it's own set of functions
    for spawning processes and the such. I know in perl they are all
    accessable from the Win32::Process module not sure in C.
  • No.6 | | 954 bytes | |

    I tried to do this but it seems like I don't get a web page returning
    right away. It is still waiting for the process to finish. I never
    get the process waiting page. I think I accounted for all file
    descriptors, but there could still be some out there. than file
    descriptors could there be anything else keeping me from displaying the
    webpage right away. I have tried closing stdout and stdin and leaving
    them both open but it still doesnt work. Here is what i have. szURL
    is where the process waiting page resides.

    pid = fork();
    if (pid){
    fclose (logFile); // file descriptors that i have next
    3 lines
    fclose (inStream);
    fclose (outStream);
    fflush (stdout);
    fclose (stdout);
    fclose (stdin);
    printf("Location: %s\n\n", szURL);
    wait();
    exit(0);
    }
    if (pid < 0){
    // prints error message
    return 0;
    }
    if (pid == 0 ) {

    // does long process
    }

    Thanks a lot!
  • No.7 | | 1307 bytes | |

    Again, I'm not to sure how this is done in C but in perl you can
    execute a process by placing it in ` marks.

    like you said in your original post:
    "long_process < /dev/null /dev/null 2>&1 &"

    Combining it with the forking example I gave you gives:

    use Errno qw(EAGAIN);
    FRK:
    if($pid = fork) {
    #you are now the parent process
    #this is where you would want to print out the html page
    } elsif(defined $pid) {
    #this is the child process
    #this is where you would exec the longer process

    `longer_process.pl < /dev/null /dev/null 2>&1 &`;

    } elsif($! == EAGAIN) {
    #an error occured while trying to fork a new process
    #this is a recoverable error so wait a little then try again
    sleep 5;
    redo FRK;
    } else {
    #an error occured while trying to fork that is not recoverable

    die "could not fork a process";
    }

    }

    I tried this on my server where the main program just prints out the
    word done and long_process.pl counted from 1-100000 a million times
    the html page loaded in my browser in milliseconds and I could still
    see the long_process.pl running in the background on the server process
    list. When I closed the browser window it killed the
    long_process.pl process though (just a note).

Re: returning page before long process is finished using C


max 4000 letters.
Your nickname that display:
In order to stop the spam: 4 + 3 =
QUESTION ON "WWW"

EMSDN.COM