Changeset 88:c114fb579eb4

Show
Ignore:
Timestamp:
11/18/09 15:16:12 (8 months ago)
Author:
roberto@…
Branch:
default
Message:

signal handling (SIGHUP,SIGTERM,SIGINT,SIGQUIT), and real graceful reload of master process

Files:
3 modified

Legend:

Unmodified
Added
Removed
  • utils.c

    r40 r88  
     1#include "uwsgi.h" 
     2 
    13#ifndef UNBIT 
    2  
    3 #include "uwsgi.h" 
    44 
    55void daemonize(char *logfile) { 
     
    8080 
    8181#endif 
     82 
     83char * uwsgi_get_cwd() { 
     84 
     85        int newsize = 256 ; 
     86        char *cwd ; 
     87 
     88        cwd = malloc(newsize); 
     89        if (cwd == NULL) { 
     90                perror("malloc()"); 
     91                exit(1); 
     92        }        
     93 
     94        if (getcwd(cwd, newsize) == NULL) { 
     95                newsize = errno; 
     96                fprintf(stderr,"need a bigger buffer (%d bytes) for getcwd(). doing reallocation.\n", newsize); 
     97                free(cwd); 
     98                cwd = malloc(newsize); 
     99                if (cwd == NULL) { 
     100                        perror("malloc()"); 
     101                        exit(1); 
     102                }                
     103                if (getcwd(cwd, newsize) == NULL) { 
     104                        perror("getcwd()"); 
     105                        exit(1); 
     106                } 
     107        } 
     108 
     109        return cwd; 
     110         
     111} 
  • uwsgi.c

    r87 r88  
    144144struct timeval start_of_uwsgi ; 
    145145 
     146char *sharedarea ; 
     147 
    146148#ifndef UNBIT 
    147149#ifndef ROCK_SOLID 
     
    208210        } 
    209211        else { 
    210                 goodbye_cruel_world() ; 
    211         } 
     212                reload_me(); 
     213        } 
     214} 
     215 
     216void reload_me() { 
     217        exit(UWSGI_RELOAD_CODE); 
     218} 
     219 
     220void end_me() { 
     221        exit(UWSGI_END_CODE); 
    212222} 
    213223 
     
    219229void kill_them_all() { 
    220230        int i ; 
    221         fprintf(stderr,"...killing workers...\n"); 
     231        fprintf(stderr,"SIGINT/SIGQUIT received...killing workers...\n"); 
    222232        for(i=1;i<=numproc;i++) {        
    223                 kill(workers[i], SIGKILL); 
    224         } 
    225         exit(0); 
     233                kill(workers[i], SIGINT); 
     234        } 
    226235} 
    227236 
     
    230239        fprintf(stderr,"...gracefully killing workers...\n"); 
    231240        for(i=1;i<=numproc;i++) {        
    232                 kill(workers[i], SIGTERM); 
     241                kill(workers[i], SIGHUP); 
    233242        } 
    234243} 
     
    238247        fprintf(stderr,"...brutally killing workers...\n"); 
    239248        for(i=1;i<=numproc;i++) { 
    240                 kill(workers[i], SIGKILL); 
     249                kill(workers[i], SIGTERM); 
    241250        } 
    242251} 
     
    531540#endif 
    532541 
    533 int main(int argc, char *argv[]) { 
     542int main(int argc, char *argv[], char *envp[]) { 
    534543 
    535544        PyObject *wsgi_result, *wsgi_chunks, *wchunk; 
     
    550559#endif 
    551560 
     561        char *cwd ; 
     562        char *binary_path ; 
     563        int ready_to_reload = 0; 
     564        int ready_to_die = 0; 
     565         
     566        int is_a_reload = 0 ; 
     567 
    552568        PyObject *pydictkey, *pydictvalue; 
    553569 
     
    560576 
    561577 
     578        int socket_type;  
     579        socklen_t socket_type_len;  
    562580 
    563581        gettimeofday(&start_of_uwsgi, NULL) ; 
    564582 
    565583        setlinebuf(stdout); 
     584 
     585        cwd = uwsgi_get_cwd(); 
     586        binary_path = malloc(strlen(argv[0])) ; 
     587        if (binary_path == NULL) { 
     588                perror("malloc()"); 
     589                exit(1); 
     590        } 
     591        strcpy(binary_path, argv[0]); 
     592 
     593        if (!getsockopt(3, SOL_SOCKET, SO_TYPE, &socket_type, &socket_type_len)) { 
     594                fprintf(stderr, "...fd 3 is a socket, i suppose this is a graceful reload of uWSGI, i will try to do my best...\n"); 
     595                is_a_reload = 1 ; 
     596#ifdef UNBIT 
     597                /* discard the 3'th fd as we will use the fd 0 */ 
     598                close(3); 
     599#else 
     600                serverfd = 3; 
     601#endif 
     602        } 
    566603 
    567604#ifndef UNBIT 
     
    603640#ifndef UNBIT 
    604641                        case 'd': 
    605                                 daemonize(optarg); 
     642                                if (!is_a_reload) { 
     643                                        daemonize(optarg); 
     644                                } 
    606645                                break; 
    607646                        case 's': 
     
    820859 
    821860#ifndef UNBIT 
    822         if (socket_name != NULL) { 
     861        if (socket_name != NULL && !is_a_reload) { 
    823862                char *tcp_port = strchr(socket_name, ':'); 
    824863                if (tcp_port == NULL) { 
     
    903942        } 
    904943        else { 
    905                 fprintf(stderr, "spawned uWSGI master process (pid: %d)\n", mypid); 
     944                if (is_a_reload) { 
     945                        fprintf(stderr, "gracefully (RE)spawned uWSGI master process (pid: %d)\n", mypid); 
     946                } 
     947                else { 
     948                        fprintf(stderr, "spawned uWSGI master process (pid: %d)\n", mypid); 
     949                } 
    906950                workers = malloc(sizeof(pid_t)*numproc+1); 
    907951        } 
     
    928972                if (pid == 0 ) { 
    929973                        mypid = getpid(); 
     974                        if (serverfd != 0 && master_process == 1) { 
     975                                /* close STDIN for workers */ 
     976                                close(0); 
     977                        } 
    930978                        break; 
    931979                } 
     
    946994        if (getpid() == masterpid && master_process == 1) { 
    947995                /* route signals to workers... */ 
    948                 signal(SIGTERM, (void *) &grace_them_all); 
    949                 signal(SIGINT, (void *) &reap_them_all); 
     996                signal(SIGHUP, (void *) &grace_them_all); 
     997                signal(SIGTERM, (void *) &reap_them_all); 
     998                signal(SIGINT, (void *) &kill_them_all); 
    950999                signal(SIGQUIT, (void *) &kill_them_all); 
    9511000                for(;;) { 
     1001                        if (ready_to_die >= numproc) { 
     1002                                fprintf(stderr,"goodbye to uWSGI.\n"); 
     1003                                exit(0); 
     1004                        }                
     1005                        if (ready_to_reload >= numproc) { 
     1006                                fprintf(stderr,"binary reloading uWSGI...\n"); 
     1007                                if (chdir(cwd)) { 
     1008                                        perror("chdir()"); 
     1009                                        exit(1); 
     1010                                } 
     1011                                /* check fd table (a module can obviosly open some fd on initialization...) */ 
     1012                                fprintf(stderr,"closing all fds > 2 (_SC_OPEN_MAX = %ld)...\n",sysconf(_SC_OPEN_MAX)); 
     1013                                for(i=3;i<sysconf(_SC_OPEN_MAX);i++) { 
     1014                                        if (i == serverfd) { 
     1015                                                continue ; 
     1016                                        } 
     1017                                        close(i); 
     1018                                } 
     1019                                if (serverfd != 3) { 
     1020                                        if (dup2(serverfd,3) < 0) { 
     1021                                                perror("dup2()"); 
     1022                                                exit(1); 
     1023                                        } 
     1024                                } 
     1025                                fprintf(stderr,"running %s\n", binary_path); 
     1026                                strcpy(argv[0], binary_path); 
     1027                                execve(binary_path, argv, envp); 
     1028                                perror("execve()"); 
     1029                                exit(1); 
     1030                        } 
    9521031                        diedpid = waitpid(WAIT_ANY , &waitpid_status, 0) ; 
    9531032                        if (diedpid == -1) { 
     
    9571036                                exit(1); 
    9581037                        } 
     1038                        /* check for reloading */ 
     1039                        if (WIFEXITED(waitpid_status)) { 
     1040                                if (WEXITSTATUS(waitpid_status) == UWSGI_RELOAD_CODE) { 
     1041                                        ready_to_reload++; 
     1042                                        continue; 
     1043                                } 
     1044                                else if (WEXITSTATUS(waitpid_status) == UWSGI_END_CODE) { 
     1045                                        ready_to_die++; 
     1046                                        continue; 
     1047                                } 
     1048                        } 
    9591049                        fprintf(stderr,"DAMN ! process %d died :( trying respawn ...\n", diedpid); 
    9601050                        gettimeofday(&last_respawn, NULL) ; 
    9611051                        if (last_respawn.tv_sec == respawn_delta) { 
    9621052                                fprintf(stderr,"worker respawning too fast !!! i have to sleep a bit...\n"); 
     1053                                /* TODO, user configurable fork throttler */ 
    9631054                                sleep(2); 
    9641055                        } 
     
    10041095        } 
    10051096 
    1006         signal(SIGINT, (void *) &goodbye_cruel_world); 
     1097        /* gracefully reload */ 
     1098        signal(SIGHUP, (void *) &gracefully_kill); 
     1099        /* close the process (useful for master INT) */ 
     1100        signal(SIGINT, (void *) &end_me); 
     1101        /* brutally reload */ 
     1102        signal(SIGTERM, (void *) &reload_me); 
    10071103 
    10081104 
     
    10121108#endif 
    10131109#endif 
    1014  
    1015         /* the best job for SIGTERM is to gracefully kill a process. */ 
    1016         signal(SIGTERM, (void *) &gracefully_kill); 
    10171110 
    10181111        while(manage_next_request) { 
     
    14841577        } 
    14851578 
    1486         goodbye_cruel_world(); 
     1579        if (manage_next_request == 0) { 
     1580                reload_me(); 
     1581        } 
     1582        else { 
     1583                goodbye_cruel_world(); 
     1584        } 
    14871585 
    14881586        /* never here */ 
  • uwsgi.h

    r85 r88  
    5151 
    5252#define PAGE_SIZE 4096 
     53 
     54#define UWSGI_RELOAD_CODE 17 
     55#define UWSGI_END_CODE 30 
    5356 
    5457 
     
    121124 
    122125 
     126char *uwsgi_get_cwd(void); 
    123127 
    124128void goodbye_cruel_world(void); 
     
    127131void kill_them_all(void); 
    128132void grace_them_all(void); 
     133void reload_me(void); 
     134void end_me(void); 
    129135int bind_to_unix(char *, int,  int , int ); 
    130136int bind_to_tcp(char *, int , char *);