Changeset 6154

Show
Ignore:
Timestamp:
05/11/10 15:04:24 (3 years ago)
Author:
Cyrus
Message:

upsd/appsd: Add support for watching and automatically restarting daemons

Location:
luci2
Files:
1 added
4 modified

Legend:

Unmodified
Added
Removed
  • luci2/appsd/appsd.h

    r5983 r6154  
    1212#ifndef APPSD_RUNLEVEL_DEFAULT 
    1313#define APPSD_RUNLEVEL_DEFAULT 2 
     14#endif 
     15 
     16#ifndef APPSD_BARRIER_DEFAULT 
     17#define APPSD_BARRIER_DEFAULT 60 
    1418#endif 
    1519 
  • luci2/appsd/initd.c

    r6031 r6154  
    2626#include <syslog.h> 
    2727#include <unistd.h> 
     28#include <stdio.h> 
    2829#include <fcntl.h> 
    2930#include <limits.h> 
     31#include <ctype.h> 
    3032 
    3133#include "ucix.h" 
    3234#include "uloop.h" 
    33 #include "upsd.h" 
     35#include "upsd-extension.h" 
    3436#include "appsd.h" 
    3537 
     
    4850    char name[]; 
    4951} *spawns = NULL; 
     52 
     53static struct appsd_init_watch { 
     54    struct appsd_init_watch *next; 
     55    pid_t pid; 
     56    time_t barrier; 
     57    char name[]; 
     58} *watched = NULL; 
    5059 
    5160static volatile pid_t checkpid = 0; 
     
    190199 
    191200        s->pid = pid; 
     201    } 
     202} 
     203 
     204 
     205static void appsd_check_watched(pid_t pid) { 
     206    struct appsd_init_watch *watched = context, *c, *d = NULL; 
     207    for (c = watched; c; d = c, c = c->next) { 
     208        if (c->pid == pid) { 
     209            if (c->barrier < time(NULL)) { 
     210                libupsd_service_control(state, c->name, UPSD_ACTION_START, 0); 
     211            } else { 
     212                APPSD_LOG_WARN("%s failed too fast. Giving Up."); 
     213            } 
     214            if (d) { 
     215                d->next = c->next; 
     216            } else { 
     217                watched = c->next; 
     218            } 
     219            free(c); 
     220            break; 
     221        } 
    192222    } 
    193223} 
     
    215245            if (s) { 
    216246                appsd_init_spawn(s->name, NULL); 
     247            } else { 
     248                appsd_check_watched(checkpid); 
    217249            } 
    218250            checkpid = 0; 
     
    231263} 
    232264 
     265static int appsd_hook_start 
     266(void *context, upsd_init_t *init, upsd_action_t action, uint16_t flags) { 
     267    if (action != UPSD_ACTION_START && action != UPSD_ACTION_RESTART 
     268    && action != UPSD_ACTION_FORCERELOAD) { 
     269        return 0; 
     270    } 
     271 
     272    struct appsd_init_watch *watched = context, *c; 
     273    int respawn = 0; 
     274    pid_t pid = 0; 
     275    const char *pidfile = NULL; 
     276 
     277    for (char **c = init->options; *c; c++) {   /* Parsing daemon options */ 
     278        if (!strncmp(*c, "X-Daemon-Pidfile:", 17)) { 
     279            pidfile = *c + 17; 
     280            while (isspace(*pidfile)) { 
     281                pidfile++; 
     282            } 
     283        } else if (!strncmp(*c, "X-Daemon-Respawn:", 17)) { 
     284            respawn = 1; 
     285        } 
     286    } 
     287 
     288    if (respawn) { 
     289        char line[16]; 
     290        FILE *fp = fopen(pidfile, "r"); 
     291        if (fp) { 
     292            if (fgets(line, sizeof(line), fp)) { 
     293                pid = (pid_t)atoi(line); 
     294            } 
     295            fclose(fp); 
     296        } 
     297        if (pid) { 
     298            for (c = watched; c; c = c->next) { 
     299                if (!strcmp(c->name, *init->provides)) { 
     300                    break; 
     301                } 
     302            } 
     303            if (!c) { 
     304                if ((c = malloc(sizeof(struct appsd_init_watch) 
     305                            + strlen(*init->provides) + 1))) { 
     306                    c->next = watched; 
     307                    memcpy(c->name, *init->provides, strlen(*init->provides)+1); 
     308                    watched = c; 
     309                } 
     310            } 
     311 
     312            if (c) { 
     313                c->pid = pid; 
     314                c->barrier = time(NULL) + APPSD_BARRIER_DEFAULT; 
     315            } 
     316        } 
     317    } 
     318    return 0; 
     319} 
     320 
     321static int appsd_hook_stop 
     322(void *context, upsd_init_t *init, upsd_action_t action, uint16_t flags) { 
     323    if (action != UPSD_ACTION_STOP && action != UPSD_ACTION_RESTART 
     324    && action != UPSD_ACTION_FORCERELOAD) { 
     325        return 0; 
     326    } 
     327 
     328    struct appsd_init_watch *watched = context, *c, *d = NULL; 
     329    int respawn = 0; 
     330 
     331    for (char **c = init->options; *c; c++) {   /* Parsing daemon options */ 
     332        if (!strncmp(*c, "X-Daemon-Respawn:", 17)) { 
     333            respawn = 1; 
     334            break; 
     335        } 
     336    } 
     337 
     338    if (respawn) { 
     339        for (c = watched; c; d = c, c = c->next) { 
     340            if (!strcmp(c->name, *init->provides)) { 
     341                if (d) { 
     342                    d->next = c->next; 
     343                } else { 
     344                    watched = c->next; 
     345                } 
     346                free(c); 
     347                break; 
     348            } 
     349        } 
     350    } 
     351    return 0; 
     352} 
     353 
    233354 
    234355int appsd_init(int argc, const char **argv) { 
     
    273394    libupsd_scan_inscfg(state, NULL); 
    274395    libupsd_scan_initdir(state, NULL); 
     396    libupsd_hook_register(state, appsd_hook_start, watched, 0, UPSD_HOOK_AFTER); 
     397    libupsd_hook_register(state, appsd_hook_stop, watched, 0, UPSD_HOOK_BEFORE); 
    275398 
    276399    ubus_ctx = ubus_ctx_alloc("init", "initd"); 
  • luci2/openwrt-feed/upsd/Makefile

    r6006 r6154  
    1616    $(INSTALL_DIR) $(1)/usr/include/ 
    1717    $(CP) $(PKG_BUILD_DIR)/upsd.h $(1)/usr/include/ 
     18    $(CP) $(PKG_BUILD_DIR)/upsd-extension.h $(1)/usr/include/ 
    1819    $(INSTALL_DIR) $(1)/usr/lib/ 
    1920    $(CP) $(PKG_BUILD_DIR)/*.so $(1)/usr/lib/ 
  • luci2/upsd/core.h

    r5829 r6154  
    55#include <sys/types.h> 
    66#include <stdint.h> 
    7 #include "upsd.h" 
     7#include "upsd-extension.h" 
    88#include "upsd_config.h" 
    99 
     
    3131typedef struct upsd_inst upsd_inst_t; 
    3232typedef struct upsd_initlist upsd_initlist_t; 
    33 typedef struct upsd_handler upsd_handler_t; 
    3433typedef struct upsd_extension upsd_extension_t; 
    35 typedef union upsd_handle upsd_handle_t; 
    3634 
    37 #define UPSD_ACTION_INTERNAL_CLEAN  ((upsd_action_t) -1) 
    38  
    39 /* Status handle for asynchronous init actions */ 
    40 union upsd_handle { 
    41     pid_t pid; 
    42     int descriptor; 
    43     void *pointer; 
    44 }; 
    45  
    46 /* Dynamic state part of a service, changing throughout commands */ 
    47 struct upsd_handler { 
    48     uint16_t flags; 
    49     uint16_t awaiting; 
    50     int16_t status; 
    51     time_t timeout; 
    52     upsd_handle_t handle; 
    53 }; 
    54  
    55 /* Service dataset */ 
    56 struct upsd_init { 
    57     uint16_t flags; 
    58     void *identifier; 
    59     char **options; 
    60     char **provides; 
    61     upsd_worker_t *worker; 
    62     upsd_handler_t hndl; 
    63 }; 
    6435 
    6536/* Event listener instance */