Re: Forking - a few queries

From: Daniel A. Koepke (dkoepke@california.com)
Date: 01/11/00


On Mon, 10 Jan 2000, Julian Buckley wrote:

>   if (!(fl = fopen("../log/syserr.tmp", "r"))) {
>     perror("Fatal error opening syserr.tmp!");
>     exit(1);
>   }
>
>   while (!feof(fl)) {
>     get_line(fl, line);
>     count++;
>     continue;
>   }
>   count--;

    fclose(fl);
    unlink("../log/syserr.tmp");

> 1) When I throw "exit(0)" at the end of the function (as per Daniel's
> email on a similar topic last week), the function runs but no output
> returns to the mud.  How can you make it return the data to the mud?

Use write_to_descriptor() to bypass the output buffering of CircleMUD,
otherwise the output isn't being written out until you get to the output
portion of the game loop in the child process, and since we're exiting
long before we get there, the output _seems_ to magically disappear.

> 2) On the flip side, if I leave it out - output gets returned, but
> "bin/circle" is childed each time I login, meaning when sending a
> SIGHUP, it appears twice, or thrice, etc - obviously the function
> doesn't close until exit() is called...;

Actually, the _mud_ is still running with the user in the child
process.  Try it without exit() and type, "shutdown," and you'll find that
the child Mud shuts down and leaves you in the parent Mud.

> 2) When fork()-ing, is it okay to leave a nice() call there, or is it
> redundant?;

I don't think it's redundant.  The manual pages for fork() don't
explicitly state what priority it assigns to the child process, so I can
only assume that it inherits the priority of the parent.

> 3) Is there an easier way to perform the above, or is get_line-ing
> okay?

  wc -l syslog.tmp

And instead of doing all of that, use pipes, as in,

    #define FPCMD "grep SYSERR ../log/syslog.* | wc -l"

    void
    fork_and_count (struct char_data *ch)
    {
        char buf[MAX_STRING_LENGTH];
        FILE *pipe;
        int cnt;

        if (fork() != 0)
        {
            /* Our parent process goes about on its own business. */
            return;
        }

        /************************* CHILD PROCESS *************************/

        if (!(pipe = popen(FPCMD, "r")))
        {
            perror("popen");
            write_to_descriptor(ch->desc->descriptor,
                                  "\007\007popen() failed\r\n");
            exit(0);
        }
        else if (fscanf(pipe, " %d", &cnt) != 1)
        {
            perror("fscanf");
            write_to_descriptor(ch->desc->descriptor,
                                  "\007\007fscanf() failed\r\n");
            exit(0);
        }

        sprintf(buf, "\007\007%d SYSERRs in logs!\r\n", cnt);
        write_to_descriptor(ch->desc->descriptor, buf);
        pclose(pipe);
        exit(0); /* End the child process's life. */
    }

    #undef FPCMD

...that's all mailer code, and untested, so no guarantees.  But I think it
works.  I dunno.  :)

-dak


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 04/10/01 PDT