Changeset 1d2e3c2 for ipc.c


Ignore:
Timestamp:
2006-02-02T13:59:14Z (18 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
ec3e411
Parents:
34b17d9 (diff), a49dcd5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Added RESTART command for easier upgrades without losing IPC connections.
(Obviously only works well for forking daemon mode.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • ipc.c

    r34b17d9 r1d2e3c2  
    22  * BitlBee -- An IRC to other IM-networks gateway                     *
    33  *                                                                    *
    4   * Copyright 2002-2004 Wilmer van der Gaast and others                *
     4  * Copyright 2002-2006 Wilmer van der Gaast and others                *
    55  \********************************************************************/
    66
     
    3030
    3131GSList *child_list = NULL;
    32 
     32static char *statefile = NULL;
    3333
    3434static void ipc_master_cmd_client( irc_t *data, char **cmd )
     
    3636        struct bitlbee_child *child = (void*) data;
    3737       
    38         if( child )
     38        if( child && cmd[1] )
    3939        {
    4040                child->host = g_strdup( cmd[1] );
     
    4343        }
    4444       
    45         ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n",
    46                              child ? child->pid : -1, cmd[2], cmd[1], cmd[3] );
     45        if( g_strcasecmp( cmd[0], "CLIENT" ) == 0 )
     46                ipc_to_children_str( "OPERMSG :Client connecting (PID=%d): %s@%s (%s)\r\n",
     47                                     child ? child->pid : -1, cmd[2], cmd[1], cmd[3] );
    4748}
    4849
     
    7475}
    7576
     77void ipc_master_cmd_restart( irc_t *data, char **cmd )
     78{
     79        struct bitlbee_child *child = (void*) data;
     80       
     81        if( global.conf->runmode != RUNMODE_FORKDAEMON )
     82        {
     83                /* Tell child that this is unsupported. */
     84                return;
     85        }
     86       
     87        global.restart = -1;
     88        bitlbee_shutdown( NULL );
     89}
     90
    7691static const command_t ipc_master_commands[] = {
    7792        { "client",     3, ipc_master_cmd_client,     0 },
     93        { "hello",      0, ipc_master_cmd_client,     0 },
    7894        { "die",        0, ipc_master_cmd_die,        0 },
    7995        { "wallops",    1, NULL,                      IPC_CMD_TO_CHILDREN },
     
    8298        { "rehash",     0, ipc_master_cmd_rehash,     0 },
    8399        { "kill",       2, NULL,                      IPC_CMD_TO_CHILDREN },
     100        { "restart",    0, ipc_master_cmd_restart,    0 },
    84101        { NULL }
    85102};
     
    140157        irc_write( irc, ":%s!%s@%s KILL %s :%s", irc->mynick, irc->mynick, irc->myhost, irc->nick, cmd[2] );
    141158        irc_abort( irc, 0, "Killed by operator: %s", cmd[2] );
     159}
     160
     161static void ipc_child_cmd_hello( irc_t *irc, char **cmd )
     162{
     163        if( irc->status < USTATUS_LOGGED_IN )
     164                ipc_to_master_str( "HELLO\r\n" );
     165        else
     166                ipc_to_master_str( "HELLO %s %s :%s\r\n", irc->host, irc->nick, irc->realname );
    142167}
    143168
     
    149174        { "rehash",     0, ipc_child_cmd_rehash,      0 },
    150175        { "kill",       2, ipc_child_cmd_kill,        0 },
     176        { "hello",      0, ipc_child_cmd_hello,       0 },
    151177        { NULL }
    152178};
     
    385411        child_list = NULL;
    386412}
     413
     414char *ipc_master_save_state()
     415{
     416        char *fn = g_strdup( "/tmp/bee-restart.XXXXXX" );
     417        int fd = mkstemp( fn );
     418        GSList *l;
     419        FILE *fp;
     420        int i;
     421       
     422        if( fd == -1 )
     423        {
     424                log_message( LOGLVL_ERROR, "Could not create temporary file: %s", strerror( errno ) );
     425                g_free( fn );
     426                return NULL;
     427        }
     428       
     429        /* This is more convenient now. */
     430        fp = fdopen( fd, "w" );
     431       
     432        for( l = child_list, i = 0; l; l = l->next )
     433                i ++;
     434       
     435        /* Number of client processes. */
     436        fprintf( fp, "%d\n", i );
     437       
     438        for( l = child_list; l; l = l->next )
     439                fprintf( fp, "%d %d\n", ((struct bitlbee_child*)l->data)->pid,
     440                                        ((struct bitlbee_child*)l->data)->ipc_fd );
     441       
     442        if( fclose( fp ) == 0 )
     443        {
     444                return fn;
     445        }
     446        else
     447        {
     448                unlink( fn );
     449                g_free( fn );
     450                return NULL;
     451        }
     452}
     453
     454void ipc_master_set_statefile( char *fn )
     455{
     456        statefile = g_strdup( fn );
     457}
     458
     459int ipc_master_load_state()
     460{
     461        struct bitlbee_child *child;
     462        FILE *fp;
     463        int i, n;
     464       
     465        if( statefile == NULL )
     466                return 0;
     467        fp = fopen( statefile, "r" );
     468        unlink( statefile );    /* Why do it later? :-) */
     469        if( fp == NULL )
     470                return 0;
     471       
     472        if( fscanf( fp, "%d", &n ) != 1 )
     473        {
     474                log_message( LOGLVL_WARNING, "Could not import state information for child processes." );
     475                fclose( fp );
     476                return 0;
     477        }
     478       
     479        log_message( LOGLVL_INFO, "Importing information for %d child processes.", n );
     480        for( i = 0; i < n; i ++ )
     481        {
     482                child = g_new0( struct bitlbee_child, 1 );
     483               
     484                if( fscanf( fp, "%d %d", &child->pid, &child->ipc_fd ) != 2 )
     485                {
     486                        log_message( LOGLVL_WARNING, "Unexpected end of file: Only processed %d clients.", i );
     487                        g_free( child );
     488                        fclose( fp );
     489                        return 0;
     490                }
     491                child->ipc_inpa = gaim_input_add( child->ipc_fd, GAIM_INPUT_READ, ipc_master_read, child );
     492               
     493                child_list = g_slist_append( child_list, child );
     494        }
     495       
     496        ipc_to_children_str( "HELLO\r\n" );
     497        ipc_to_children_str( "OPERMSG :New BitlBee master process started (version " BITLBEE_VERSION ")\r\n" );
     498       
     499        return 1;
     500}
Note: See TracChangeset for help on using the changeset viewer.