Пример #1
0
/* The Execute function. Note that we use vfork() rather than fork. Vfork has
 a special semantic in that the child process runs in the parent address space
 until exec is called in the child. The child also run first and suspend the
 parent process until exec or exit is called */
Process_T Command_execute(T C) {
        assert(C);
        volatile int exec_error = 0;
        Process_T P = Process_new();
        P->env = (char**)List_toArray(C->env);
        P->args = (char**)List_toArray(C->args);
        createPipes(P);
        if ((P->pid = vfork()) < 0) {
                ERROR("Command: fork failed -- %s\n", System_getLastError());
                Process_free(&P);
                return NULL;
        }
        // Child
        else if (P->pid == 0) { 
                if (C->working_directory) {
                        if (! Dir_chdir(C->working_directory)) {
                                exec_error = errno;
                                ERROR("Command: sub-process cannot change working directory to '%s' -- %s\n", C->working_directory, System_getLastError());
                                _exit(errno);
                        }
                }
                if (C->uid)
                        P->uid = (setuid(C->uid) != 0) ? ERROR("Command: Cannot change process uid to '%d' -- %s\n", C->uid, System_getLastError()), getuid() : C->uid;
                else
                        P->uid = getuid();
                if (C->gid)
                        P->gid = (setgid(C->gid) != 0) ? ERROR("Command: Cannot change process gid to '%d' -- %s\n", C->gid, System_getLastError()), getgid() : C->gid;
                else
                        P->gid = getgid();
                setsid(); // Loose controlling terminal
                setupChildPipes(P);
                // Close all descriptors except stdio
                int descriptors = getdtablesize();
                for (int i = 3; i < descriptors; i++)
                        close(i);
                // Unblock any signals and reset signal handlers
                sigset_t mask;
                sigemptyset(&mask);
                pthread_sigmask(SIG_SETMASK, &mask, NULL);
                signal(SIGINT, SIG_DFL);
                signal(SIGQUIT, SIG_DFL);
                signal(SIGABRT, SIG_DFL);
                signal(SIGTERM, SIG_DFL);
                signal(SIGPIPE, SIG_DFL);
                signal(SIGCHLD, SIG_DFL); 
                signal(SIGUSR1, SIG_DFL);
                signal(SIGHUP, SIG_IGN);  // Ensure future opens won't allocate controlling TTYs
                // Execute the program
                execve(P->args[0], P->args, P->env);
                exec_error = errno;
                _exit(errno);
        }
        // Parent
        if (exec_error != 0)
                Process_free(&P);
        else 
                setupParentPipes(P);
        errno = exec_error;
        return P;
}
Пример #2
0
void sigHandler( Signal *s )
{
    int PID;
    Process *p = NULL;
    Signal *t;
    
    gotSignal = 1;

    /*
     * Switch that takes care of the signal that was caught
     */
    switch( Signal_getNum(s) )
    {
        /*
         * Message from the child
         */
        case SIGCHLD:

            PID = Signal_getCaller(s);

            switch( Signal_getCode(s) )
            {
                /*
                 * Child exited
                 */
                case CLD_EXITED:
                    printf("\nCHILD exited: PID %d\n", PID );
                    p = ProcControl_removePID( PID );
                    if( p != NULL )
                    {
                        Process_wait( p, PROCESS_NOWAIT );
                        Process_free( p );
                    }
                    else
                    {
                        if( RUNNING )
                        {
                            Process_free( RUNNING );
                        }
                    }

                    if( p == RUNNING )
                        RUNNING = NULL;

                    break;

                /*
                 * Child got killed
                 */
                case CLD_KILLED:
                    printf("\nCHILD killed: PID %d\n", PID );
                    p = ProcControl_removePID( PID );
                    if( p != NULL )
                    {
                        Process_wait( p, PROCESS_NOWAIT );
                        Process_free( p );
                    }

                    if( p == RUNNING )
                        RUNNING = NULL;

                    break;

                /*
                 * Child got suspended
                 */
                case CLD_STOPPED:

                        p = ProcControl_getPID( PID );
                        if( p != NULL )
                        {
                            printf("\nSuspended %d ", Process_getPID(p) );
                            Process_printCommand( p, stdout );
                            printf("\n");
                        }
                        else
                        {
                            fprintf( stderr, "Process stopped that wasn't in"
                                    "List: %d\n", PID );
                        }
                        break;

                case CLD_CONTINUED:

                        fprintf(stderr, "LOOOOOOO\n");
                        break;

            }

            break;

            /* 
             * Caught the Cntrol-Z 
             * 
             * We need to suspend the child
             */
       case SIGTSTP:

                if( RUNNING != NULL )
                {
                    Process_suspend( RUNNING );
                    RUNNING = NULL;
                }
                else
                {
                    printf("\n");
                }

            break;

            /*
             * Ctrl-C - we need to kill the current child
             */

       case SIGINT:
            if( RUNNING != NULL )
            {
                Process_kill( RUNNING );
            }
            else
            {
                printf("\n");
            }

            break;

            /*
             * Seg fault handler
             */
       case SIGSEGV:
            fprintf(stderr, "\nSeg fault!!!\n");
            exit(-1);
    }
}
Пример #3
0
static int _commandExecute(Service_T S, command_t c, char *msg, int msglen, int64_t *timeout) {
        ASSERT(S);
        ASSERT(c);
        ASSERT(msg);
        msg[0] = 0;
        int status = -1;
        Command_T C = NULL;
        TRY
        {
                // May throw exception if the program doesn't exist (was removed while Monit was up)
                C = Command_new(c->arg[0], NULL);
        }
        ELSE
        {
                snprintf(msg, msglen, "Program %s failed: %s", c->arg[0], Exception_frame.message);
        }
        END_TRY;
        if (C) {
                for (int i = 1; i < c->length; i++)
                        Command_appendArgument(C, c->arg[i]);
                if (c->has_uid)
                        Command_setUid(C, c->uid);
                if (c->has_gid)
                        Command_setGid(C, c->gid);
                Command_setEnv(C, "MONIT_DATE", Time_string(Time_now(), (char[26]){}));
                Command_setEnv(C, "MONIT_SERVICE", S->name);
                Command_setEnv(C, "MONIT_HOST", Run.system->name);
                Command_setEnv(C, "MONIT_EVENT", c == S->start ? "Started" : c == S->stop ? "Stopped" : "Restarted");
                Command_setEnv(C, "MONIT_DESCRIPTION", c == S->start ? "Started" : c == S->stop ? "Stopped" : "Restarted");
                if (S->type == Service_Process) {
                        Command_vSetEnv(C, "MONIT_PROCESS_PID", "%d", Util_isProcessRunning(S, false));
                        Command_vSetEnv(C, "MONIT_PROCESS_MEMORY", "%ld", S->inf->priv.process.mem_kbyte);
                        Command_vSetEnv(C, "MONIT_PROCESS_CHILDREN", "%d", S->inf->priv.process.children);
                        Command_vSetEnv(C, "MONIT_PROCESS_CPU_PERCENT", "%d", S->inf->priv.process.cpu_percent);
                }
                Process_T P = Command_execute(C);
                Command_free(&C);
                if (P) {
                        do {
                                Time_usleep(RETRY_INTERVAL);
                                *timeout -= RETRY_INTERVAL;
                        } while ((status = Process_exitStatus(P)) < 0 && *timeout > 0 && ! (Run.flags & Run_Stopped));
                        if (*timeout <= 0)
                                snprintf(msg, msglen, "Program %s timed out", c->arg[0]);
                        int n, total = 0;
                        char buf[STRLEN];
                        do {
                                if ((n = _getOutput(Process_getErrorStream(P), buf, sizeof(buf))) <= 0)
                                        n = _getOutput(Process_getInputStream(P), buf, sizeof(buf));
                                if (n > 0) {
                                        buf[n] = 0;
                                        DEBUG("%s", buf);
                                        // Report the first message (override existing plain timeout message if some program output is available)
                                        if (! total)
                                                snprintf(msg, msglen, "%s: %s%s", c->arg[0], *timeout <= 0 ? "Program timed out -- " : "", buf);
                                        total += n;
                                }
                        } while (n > 0 && Run.debug && total < 2048); // Limit the debug output (if the program will have endless output, such as 'yes' utility, we have to stop at some point to not spin here forever)
                        Process_free(&P); // Will kill the program if still running
                }
        }
Пример #4
0
static void _gc_service(Service_T *s) {

        ASSERT(s&&*s);

        if ((*s)->program) {
                if ((*s)->program->P)
                        Process_free(&(*s)->program->P);
                if ((*s)->program->C)
                        Command_free(&(*s)->program->C);
                if ((*s)->program->args)
                        gccmd(&(*s)->program->args);
                StringBuffer_free(&((*s)->program->output));
                FREE((*s)->program);
        }

        if((*s)->portlist)
                _gcppl(&(*s)->portlist);

        if((*s)->filesystemlist)
                _gcfilesystem(&(*s)->filesystemlist);

        if((*s)->icmplist)
                _gcicmp(&(*s)->icmplist);

        if((*s)->maillist)
                gc_mail_list(&(*s)->maillist);

        if((*s)->resourcelist)
                _gcpql(&(*s)->resourcelist);

        if((*s)->inf)
                _gc_inf(&(*s)->inf);

        if((*s)->timestamplist)
                _gcptl(&(*s)->timestamplist);

        if((*s)->actionratelist)
                _gcparl(&(*s)->actionratelist);

        if((*s)->sizelist)
                _gcso(&(*s)->sizelist);

        if((*s)->matchlist)
                _gcmatch(&(*s)->matchlist);

        if((*s)->matchignorelist)
                _gcmatch(&(*s)->matchignorelist);

        if((*s)->checksum)
                _gcchecksum(&(*s)->checksum);

        if((*s)->perm)
                _gcperm(&(*s)->perm);

        if ((*s)->statuslist)
                _gcstatus(&(*s)->statuslist);

        if ((*s)->every.type == EVERY_CRON || (*s)->every.type == EVERY_NOTINCRON)
                FREE((*s)->every.spec.cron);

        if((*s)->uid)
                _gcuid(&(*s)->uid);

        if((*s)->euid)
                _gcuid(&(*s)->euid);

        if((*s)->gid)
                _gcgid(&(*s)->gid);

        if((*s)->pidlist)
                _gcpid(&(*s)->pidlist);

        if((*s)->ppidlist)
                _gcppid(&(*s)->ppidlist);

        if((*s)->dependantlist)
                _gcpdl(&(*s)->dependantlist);

        if((*s)->start)
                gccmd(&(*s)->start);

        if((*s)->stop)
                gccmd(&(*s)->stop);

        if((*s)->action_DATA)
                _gc_eventaction(&(*s)->action_DATA);

        if((*s)->action_EXEC)
                _gc_eventaction(&(*s)->action_EXEC);

        if((*s)->action_INVALID)
                _gc_eventaction(&(*s)->action_INVALID);

        if((*s)->action_NONEXIST)
                _gc_eventaction(&(*s)->action_NONEXIST);

        if((*s)->action_FSFLAG)
                _gc_eventaction(&(*s)->action_FSFLAG);

        if((*s)->action_MONIT_START)
                _gc_eventaction(&(*s)->action_MONIT_START);

        if((*s)->action_MONIT_STOP)
                _gc_eventaction(&(*s)->action_MONIT_STOP);

        if((*s)->action_MONIT_RELOAD)
                _gc_eventaction(&(*s)->action_MONIT_RELOAD);

        if((*s)->action_ACTION)
                _gc_eventaction(&(*s)->action_ACTION);

        if((*s)->eventlist)
                gc_event(&(*s)->eventlist);

        FREE((*s)->name);
        FREE((*s)->path);

        (*s)->next = NULL;

        FREE(*s);

}