Beispiel #1
0
static rstatus_t
stats_master_send_rsp(int *psd)
{
    int n;
	ssize_t len;
    int sd;
	int i;
	nc_channel_msg_t     message;
	char buf[1000];
	memset(buf, 0, sizeof(char)*1000);
	char *snd_buf = NULL;

	memset(&message, 0, sizeof(nc_channel_msg_t));
	message.command = NC_CMD_GET_STATS;
	
	if (*psd) {
		sd = accept(*psd, NULL, NULL);
		if (sd < 0) {
	        log_error("accept on m %d failed: %s", sd, strerror(errno));
	        return NC_ERROR;
	    }
	}
	
	// still in reconfiguration process 
	if (nc_reload_start) {
		sprintf(buf, "%s", "no stats get due to still during reconfiguration period.");
		if (*psd) {
			len = nc_strlen(buf)+1;
			len = nc_sendn(sd, buf, len);
			if (len < 0) {
				log_error("send stats on sd %d failed: %s", sd, strerror(errno));

			}
			close(sd);
		}
		return NC_OK;
	}

	//broadcast
    for (i = 0; i < nc_last_process; i++) 
	{
        if (nc_processes[i].pid == -1 || nc_processes[i].pid == 0) 
		{
            continue;
        }
       
        if (nc_write_channel(nc_processes[i].channel[0],
                                  &message, sizeof(nc_channel_msg_t))
           == NC_OK)
        {
			if (nc_set_blocking(nc_processes[i].channel[0]) < 0) {
		    	log_error("set channel %d block failed while core timeout %s", 
		        nc_processes[i].channel[0] , strerror(errno));
				continue;
			}
		
			n = nc_read_channel(nc_processes[i].channel[0], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
			if (env_global.ctrl_msg.command != NC_CMD_GET_STATS || n < 0) {
				log_error("failure: get stats from worker %d receive length,  %s", 
		        nc_processes[i].channel[0] , strerror(errno));
			} else {
				log_error("success: get stats from worker %d receive length, %d", 
		        nc_processes[i].channel[0] , n);

				snd_buf = nc_alloc(n + n);				
				len = nc_recvn(nc_processes[i].channel[0], snd_buf, n);
				if (len < 0) {
					if (*psd) {
						log_error("recv stats on sd %d failed: %s", sd, strerror(errno));
					}
					nc_free(snd_buf);
					snd_buf = NULL;
        			continue;
				}
				if (*psd) {
					len = nc_sendn(sd, snd_buf, len);
					if (len < 0) {
						log_error("send stats on sd %d failed: %s", sd, strerror(errno));
						nc_free(snd_buf);
						snd_buf = NULL;
						continue;
					}
				}
	
				len = nc_write(env_global.stats_fd, snd_buf, len);
				if (len < 0) {
					log_error("nc_write %d failed: %s", env_global.stats_fd, strerror(errno));
					continue;
			    }

				
				nc_free(snd_buf);
				snd_buf = NULL;

			}

			

			if (nc_set_nonblocking(nc_processes[i].channel[0]) < 0) {
				log_error("set channel %d nonblock failed while core timeout %s", 
				        nc_processes[i].channel[0] , strerror(errno));
			}

        }
    }
	
	if (*psd) {
		shutdown(sd, SHUT_RDWR);
		close(sd);
	}
    return NC_OK;
}
Beispiel #2
0
void
tw_master_cycle(struct env_master* env)
{   
    int         sigio;
    sigset_t           set;
    struct itimerval   itv;
    unsigned int       live;

	// msec: 1/1000 sec
    unsigned int       delay;
	int i, r;
	struct timeval tv;
   

	nc_process_role = NC_PROCESS_MASTER;
	nc_setproctitle("master");

    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);
    //reconfigure
    sigaddset(&set, SIGHUP);  
    // noaccept
    sigaddset(&set, SIGWINCH);
	
    sigaddset(&set, SIGTERM);
    sigaddset(&set, SIGQUIT);
	
    //sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
    //sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));


    // block above singalling
    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
        log_error("sigprocmask() failed %s", strerror(errno));
    }
    sigemptyset(&set);

    nc_start_worker_processes(env);

    // master
    //delay = 1000;
	delay = 1; // 1ms
    sigio = 0;
    live = 1;
	nc_reload_start = 0;

    for ( ;; ) {
        // no singal, alarm event
        if (nc_sigalarm) {	 
        	sigio = 0;
		   	// like slow start
            // delay *= 2;			
            nc_sigalarm= 0;
			
			rebuild_fdset();
			tv.tv_sec = 0;
			tv.tv_usec = 0;
			//log_error("tyson, %d", fds_width);
			r = select(fds_width, &rdfs, NULL, NULL, &tv);
			if (r) {
				for (i = 0; i < fds_width; i++) {
					if (FD_ISSET(i, &rdfs)){
						nc_read_channel(i, &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
					}	
				}
			}
			
			/*
			for (i = 0; i < nc_last_process; i++) {
				if (nc_processes[i].pid == -1 || nc_processes[i].pid == 0){
					continue;
				}

				
				//log_debug(LOG_ERR, "tyson here");
				nc_read_channel(nc_processes[0].channel_back[0], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
				//nc_read_channel(nc_processes[i].channel[1], &env_global.ctrl_msg, sizeof(nc_channel_msg_t));
			}*/

			
			if (nc_reload_start && !nc_cnt_reload) {
				nc_reload_start = 0;
				nc_cnt_reload = NC_CNT_RELOAD_MAGIC;
			}
         }

        log_debug("termination cycle: %d", delay);

        itv.it_interval.tv_sec = 0;
        itv.it_interval.tv_usec = 0;
        itv.it_value.tv_sec = delay / 1000;
        itv.it_value.tv_usec = (delay % 1000 ) * 1000;
	    // produce SIGALARM
        if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
        	log_debug("setitimer() failed %s", strerror(errno));
        }
	
        //log_debug("sigsuspend");
        sigsuspend(&set);
		// wake up this place
        log_debug("wake up, sigio %d", sigio);
    	 
        if (nc_reap) {
            nc_reap = 0;
            log_warn("reap children");
			
            live = nc_reap_children();
        }
	 
		// best effort, send signal via channel before death
        // if (!live && (nc_terminate || nc_quit)) {
		if (nc_terminate) {
			nc_term_children();
			sleep(1);
            nc_master_post_run(env);
	     	exit(1);
        }
		
        if (nc_terminate) {
            if (delay == 0) {
                delay = 50;
            }

            if (sigio) {
                sigio--;
                continue;
            }

            sigio = env->worker_processes;
	        // kill -9
            if (delay > 2000) {		
                nc_signal_worker_processes(SIGKILL);
            } else {
                nc_signal_worker_processes(SIGTERM);
            }

            continue;
        }

		// graceful shutdown
        if (nc_quit) {
            nc_signal_worker_processes(SIGQUIT);                 
			/*
            ls = cycle->listening.elts;
            for (n = 0; n < cycle->listening.nelts; n++) {
                if (ngx_close_socket(ls[n].fd) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
                                  ngx_close_socket_n " %V failed",
                                  &ls[n].addr_text);
                }
            }
            cycle->listening.nelts = 0;
            */

            continue;
        }

		// todo
		/*
        if (nc_restart) {
            nc_restart = 0;
            nc_start_worker_processes(env);
            live = 1;
        }
		*/
#ifdef GRACEFUL
		if (nc_reload && !nc_reload_start) {
			nc_reload = 0;  
			nc_reload_start = 1;
			nc_cnt_reload = NC_CNT_RELOAD_MAGIC;
			//reset after all worker processes reload done
			nc_signal_worker_processes(SIGHUP);
			continue;
		} else if (nc_reload) {
			log_debug(LOG_ERR, "deny reload request due to reason: still in reconfiguation status %d", nc_reload_start);
		}
#endif

    }
}