Esempio n. 1
0
int
handle_start_proc(struct request * r)
{
    fprintf(stderr, "starting proc\n");
    struct child_process * c = make_child_proc((struct svc_packet *)r->data);
    if (0 == c)
    {
        fprintf(stderr, "failed to created child process structure\n");
        return -1;
    } 
    else
    {
        if (c->start_calendar_interval)
        {
            struct timeval now;
            gettimeofday(&now, 0); 
            c->last_restart = *(next_start(&now, c->start_calendar_interval));
            queue_proc(c);
        }
        else
        {
            fprintf(stderr, "starting proc %s\n", c->label);
            gettimeofday(&c->last_restart, 0);
            spawn_proc(c);
        }
        return 0;
    }
}
Esempio n. 2
0
int
main()
{
    struct cron_spec test_spec;
    memset(&test_spec, 0, sizeof(test_spec));
    test_spec.sec[10] = 1;
    test_spec.sec_flag = 1;
    test_spec.min[3] = 1;
    test_spec.min[45] = 1;
    test_spec.min_flag = 1;
    test_spec.hour[11] = 1;
    test_spec.hour_flag = 1;
    test_spec.mday[15] = 1;
    test_spec.mday_flag = 1;
    test_spec.mon[6] = 1;
    test_spec.mon[9] = 1;
    test_spec.mon[2] = 1;
    test_spec.mon_flag = 1;
    test_spec.wday[4] = 1;
    test_spec.wday_flag = 1;
    struct timeval now;

    gettimeofday(&now, 0);
    struct timeval * timeout;
    timeout = next_start(&now, &test_spec);
    for(int i = 0; i < 1000; i++)
    {  
        struct timeval t; 
        if (timeout)
        {
            t = *timeout;
            free(timeout);
        }
        timeout = next_start(&t, &test_spec);
    }
    return 0;
}
Esempio n. 3
0
/*
 * See if we can expand region rgn by nextra bytes by using up
 * free space after or before the region.
 */
static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
		int nextra)
{
	char *p = *pp;
	char *rgn_start, *rgn_end;

	rgn_start = cxt->rgn[rgn].start;
	rgn_end = rgn_start + cxt->rgn[rgn].size;
	if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
		/* move following stuff */
		if (p < rgn_end) {
			if (nextra < 0)
				memmove(p, p - nextra, rgn_end - p + nextra);
			else
				memmove(p + nextra, p, rgn_end - p);
			if (rgn == FT_STRUCT)
				ft_node_update_after(cxt, p, nextra);
		}
		cxt->rgn[rgn].size += nextra;
		if (rgn == FT_STRINGS)
			/* assumes strings only added at beginning */
			cxt->str_anchor += nextra;
		return 1;
	}
	if (prev_end(cxt, rgn) <= rgn_start - nextra) {
		/* move preceding stuff */
		if (p > rgn_start) {
			memmove(rgn_start - nextra, rgn_start, p - rgn_start);
			if (rgn == FT_STRUCT)
				ft_node_update_before(cxt, p, -nextra);
		}
		*pp -= nextra;
		cxt->rgn[rgn].start -= nextra;
		cxt->rgn[rgn].size += nextra;
		return 1;
	}
	return 0;
}
Esempio n. 4
0
static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
			 int nextra)
{
	unsigned long size, ssize, tot;
	char *str, *next;
	enum ft_rgn_id r;

	if (!cxt->isordered) {
		unsigned long rgn_off = *pp - cxt->rgn[rgn].start;

		if (!ft_reorder(cxt, nextra))
			return 0;

		*pp = cxt->rgn[rgn].start + rgn_off;
	}
	if (ft_shuffle(cxt, pp, rgn, nextra))
		return 1;

	/* See if there is space after the strings section */
	ssize = cxt->rgn[FT_STRINGS].size;
	if (cxt->rgn[FT_STRINGS].start + ssize
			< (char *)cxt->bph + cxt->max_size) {
		/* move strings up as far as possible */
		str = (char *)cxt->bph + cxt->max_size - ssize;
		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
		cxt->rgn[FT_STRINGS].start = str;
		/* enough space now? */
		if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
			return 1;
	}

	/* how much total free space is there following this region? */
	tot = 0;
	for (r = rgn; r < FT_STRINGS; ++r) {
		char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
		tot += next_start(cxt, rgn) - r_end;
	}

	/* cast is to shut gcc up; we know nextra >= 0 */
	if (tot < (unsigned int)nextra) {
		/* have to reallocate */
		char *newp, *new_start;
		int shift;

		if (!cxt->realloc)
			return 0;
		size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
		newp = cxt->realloc(cxt->bph, size);
		if (!newp)
			return 0;
		cxt->max_size = size;
		shift = newp - (char *)cxt->bph;

		if (shift) { /* realloc can return same addr */
			cxt->bph = (struct boot_param_header *)newp;
			ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
					shift);
			for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
				new_start = cxt->rgn[r].start + shift;
				cxt->rgn[r].start = new_start;
			}
			*pp += shift;
			cxt->str_anchor += shift;
		}

		/* move strings up to the end */
		str = newp + size - ssize;
		cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
		memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
		cxt->rgn[FT_STRINGS].start = str;

		if (ft_shuffle(cxt, pp, rgn, nextra))
			return 1;
	}

	/* must be FT_RSVMAP and we need to move FT_STRUCT up */
	if (rgn == FT_RSVMAP) {
		next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
			+ nextra;
		ssize = cxt->rgn[FT_STRUCT].size;
		if (next + ssize >= cxt->rgn[FT_STRINGS].start)
			return 0;	/* "can't happen" */
		memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
		ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
		cxt->rgn[FT_STRUCT].start = next;

		if (ft_shuffle(cxt, pp, rgn, nextra))
			return 1;
	}

	return 0;		/* "can't happen" */
}
Esempio n. 5
0
int
main(int argc, char * argv[])
{
    int fd;
    struct sigaction sig;
    struct passwd * pwd = 0;
    
    if (argc == 2)
    {
        if (argv[1])
        {
            errno = 0; 
            pwd = getpwnam(argv[1]);
            if (0 == pwd)
            {
                fprintf(stderr, "getpwnam failed: %s\n", strerror(errno));
                while(1)
                {
                    pause();
                }
            }  
        } 
    }
    
    if (pwd)
    {
        sprintf(process_manager_run_dir, "/run/process-manager.%s", pwd->pw_name);
        sprintf(process_manager_socket_path, "/run/process-manager.%s/procman", pwd->pw_name);
    }
    else 
    {
        sprintf(process_manager_run_dir, "/run/process-manager");
        sprintf(process_manager_socket_path, "/run/process-manager/procman");
        we_are_root = 1;
    }
    
    (void)fprintf(stderr, "process-manager: process-manager starting...\n");

    memset(&sig, 0, sizeof(sig));
    sigfillset(&sig.sa_mask);
    sig.sa_flags = SA_SIGINFO;
    sig.sa_sigaction = handle_sigterm;
    sigaction(SIGTERM, &sig, 0);

    memset(&sig, 0, sizeof(sig));
    sigfillset(&sig.sa_mask);
    sig.sa_flags = SA_SIGINFO;
    sig.sa_sigaction = handle_sigchild;
    sigaction(SIGCHLD, &sig, 0);
       
    memset(&sig, 0, sizeof(sig));
    sigfillset(&sig.sa_mask);
    sig.sa_flags = SA_SIGINFO;
    sig.sa_sigaction = handle_sigalarm;
    sigaction(SIGALRM, &sig, 0); 

    fd = open("/dev/console", O_RDWR | O_NOCTTY);
    if (fd >= 0)
    {
        dup2(fd,0); 
        dup2(fd,1);
        dup2(fd,2);
        if (fd > 2)
            close(fd);
        (void)fprintf(stderr, "process-manager: console reopened...\n");
    }
    else
    {
        (void)fprintf(stderr, "failed to open console");
    }     

    if (we_are_root)
    {
        struct stat stat_buf;
        memset(&stat_buf, 0, sizeof(stat_buf));
        
        if (-1 == stat("/run/process-manager", &stat_buf))
        {
            fprintf(stderr, "expected stat error: %s\n", strerror(errno));
            if (-1 == mount("none", "/run", "tmpfs", 0, 0))
            {
                fprintf(stderr, "failed to mount tmpfs on /run: %s\n", strerror(errno));
                while(1)
                    pause();
            }
            fprintf(stderr, "we are root\n");
            if (-1 == mkdir("/run/process-manager", 0770))
            {
                fprintf(stderr, "failed to make dir /run/process-manager: %s\n", strerror(errno));
                while(1)
                    pause();
            }
            struct group * g = getgrnam("process-manager");
            if (g)
            {
                if (-1 == chown("/run/process-manager", -1, g->gr_gid))
                    fprintf(stderr, "chown gid %d failed: %s\n", g->gr_gid, strerror(errno));
                if (-1 == chmod("/run/process-manager", S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP
                    |S_IXGRP))
                    fprintf(stderr, "chmod failed: %s\n", strerror(errno));
            }
            else
            {
                fprintf(stderr, "getgrnam process-manager failed: %s\n", strerror(errno));
            } 
        }
    }
    else
    {
        mkdir(process_manager_run_dir, 0700);
        if (-1 == chown(process_manager_run_dir, pwd->pw_uid, pwd->pw_gid))
            fprintf(stderr, "chown failed: %s\n", strerror(errno));
    } 

    running = malloc(sizeof(*running));
    memset(running, 0, sizeof(*running));
    running->next = running; 

    waiting = malloc(sizeof(*waiting));
    memset(waiting, 0, sizeof(*waiting));
    waiting->next = waiting;
    waiting->pid = 0x7fffffff;
    waiting->last_restart.tv_sec = 0x7fffffffffffffff; 

    inactive = malloc(sizeof(*inactive));
    memset(inactive,0 ,sizeof(*inactive));
    inactive->next = inactive;

    struct sockaddr_un ctl_un;
    pid_t ctl_pid;
    socklen_t ctl_len; 
    int ctl_p_endp = launch_control_proc(pwd, process_manager_socket_path, &ctl_un, &ctl_len, &ctl_pid);

    if (ctl_p_endp < 0) //socket already exists and another instance is running
    {
        fprintf(stderr, "socket in use, ctl_p_endp: %d\n", ctl_p_endp);
        return 1;
    }
  
    if (we_are_root)
        spawn_proc(&arbitrator);

    while(0 == run_state)
    {
        int status;
        pid_t child_pid = -1;
        struct child_process * proc;  
        unsigned char restart_proc = 0; 

        if (waiting->next == waiting)
        {
            alarm(0);
        }
        else
        {
            struct timeval now;
            gettimeofday(&now, 0);
            alarm(waiting->next->last_restart.tv_sec - now.tv_sec); 
        }

        timeout = 0; 

        fprintf(stderr, "waiting for exiting childern...\n");
        unsigned char data[1024];
        unsigned int len = sizeof(data);
        if (-1 == recvfrom(ctl_p_endp, data, len, 0, &ctl_un, &ctl_len))
        {
            if (errno == EINTR)
            {
                fprintf(stderr, "process-manager: signal received: %d, run_state == %d\n", signum, run_state);
                if (timeout)
                {
                    timeout = 0;
                    struct timeval now;
                    gettimeofday(&now, 0);  
                    fprintf(stderr, "we got timeout. next timeout %ld, it is now %ld\n", waiting->next->last_restart.tv_sec,
                        now.tv_sec);
                    while(waiting->next->last_restart.tv_sec <= now.tv_sec)
                    { 
                        struct child_process * c = dequeue_proc();
                        fprintf(stderr, "restarting queued proc %s\n", c->label);
                        spawn_proc(c);
                    }
                }
                if (got_sigchild)
                {
                    got_sigchild = 0;
                    while((child_pid = waitpid(-1, &status, WNOHANG)))
                    {
                        if (child_pid < 0)
                        {
                            fprintf(stderr, "failed to get child status: %s\n", strerror(errno));
                            if (EINTR != errno) break;  
                        }
                        else
                        {
                            proc = get_process(child_pid);
                            child_pid = -1;
                            if (proc)
                            {
                                kill(-proc->pid, SIGTERM);

                                restart_proc = 0;
                                if (proc->start_calendar_interval)
                                {
                                    struct timeval now;
                                    gettimeofday(&now, 0); 
                                    proc->last_restart = *(next_start(&now, proc->start_calendar_interval));
                                    queue_proc(proc);
                                } 
                                else if (proc->keepalive_opts)
                                {
                                    int i = 0;
                                    while(proc->keepalive_opts[i])
                                    {
                                        fprintf(stderr, "keepalive opts %d:%d\n", proc->keepalive_opts[i], 
                                            proc->keepalive_opts[i + 1]);
                                        if (SUCCESSFUL_EXIT == proc->keepalive_opts[i])
                                        {
                                            if (0 <  proc->keepalive_opts[i + 1])
                                            {
                                                if (WIFEXITED(status))
                                                {
                                                    restart_proc |= 1;
                                                }
                                            }
                                            else
                                            {
                                                if (WIFSIGNALED(status))
                                                {
                                                    restart_proc |= 1;
                                                }  
                                            } 
                                        }
                                        i += 2; 
                                    } 
                                }
            
                                if (restart_proc)
                                {
                                    fprintf(stderr, "restarting %s, exec file %s\n", proc->label, proc->exec_file_path);
                                    struct timeval now;
                                    gettimeofday(&now, 0);
                                    fprintf(stderr, "%s last restart %ld it is now %ld\n", 
                                        proc->label, proc->last_restart.tv_sec, now.tv_sec);
                                    if ((proc->last_restart.tv_sec + 10) < now.tv_sec)
                                    {
                                        gettimeofday(&proc->last_restart, 0);
                                        spawn_proc(proc);
                                        fprintf(stderr, "spawn %s pid %d\n", proc->exec_file_path, proc->pid);
                                    }
                                    else
                                    {
                                        if (proc->throttle_count < 40)
                                        {   
                                            fprintf(stderr, "throttling %s\n", proc->label);
                                            gettimeofday(&proc->last_restart, 0);
                                            proc->last_restart.tv_sec += 10;
                                            proc->throttle_count++;
                                            fprintf(stderr, "%s throttle_count %d restart at %ld\n",
                                                 proc->label, proc->throttle_count, proc->last_restart.tv_sec);
                                            queue_proc(proc);
                                        } 
                                        else
                                        {
                                            fprintf(stderr, "%s exceeded throttle limit\n", proc->label);
                                            destroy_proc_struct(proc);
                                        } 
                                    } 
                                }
                                else
                                {
                                    if (WIFEXITED(status))
                                        fprintf(stderr, "process %s:%d %s exited with %d\n", proc->label, proc->pid, proc->exec_file_path, WEXITSTATUS(status));
                                    else if (WIFSIGNALED(status)) 
                                        fprintf(stderr, "process %s:%d signaled with %d\n", proc->label, proc->pid, WTERMSIG(status));
                                    destroy_proc_struct(proc);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                fprintf(stderr, "recvfrom failed: %s\n", strerror(errno));
                sleep(3); 
            }  
        }
        else
        {
            handle_data(data, len);
        }
    }

    unsigned char any_child_exists = 1;
    int status = 0;

    fprintf(stderr, "sending SIGTERM to all children...\n");
    struct child_process * v = running->next;
    while(running != v)
    {
        if (-1 == kill(-v->pid, SIGTERM))
        {
            fprintf(stderr, "process-manager: kill process group %d failed: %s\n", -v->pid, strerror(errno));
            if (-1 == kill(v->pid, SIGTERM))
            {
                fprintf(stderr, "process-manager: kill %d failed: %s\n", v->pid, strerror(errno));
            }
        }
        v = v->next;
    }
    kill(ctl_pid, SIGTERM);

    alarm(5);

    while (any_child_exists)
    {
        pid_t child = wait(&status);
        if (0 > child) 
        {
            if (ECHILD == errno) 
            {
                any_child_exists = 0;
                fprintf(stderr, "process-manager: no more children left...\n");
            }
            else if (EINTR == errno)
            {
                if (timeout)
                {
                    timeout = 0;
                    any_child_exists = 0;
                }
            }
        }   
    }
    alarm(0);

    sleep(1);
 
    close(ctl_p_endp);
    unlink(process_manager_socket_path);
    return 0;
}