~aritra1911/mc_server

b04c39944e653b49a9bbe3a2c7bcbdf7b2849ef7 — Aritra Sarkar 2 years ago eeecda0
Revert previous commit since Minix is in no shape to run this
1 files changed, 64 insertions(+), 79 deletions(-)

M main.c
M main.c => main.c +64 -79
@@ 47,12 47,7 @@ typedef struct {
    char    port[8];
} prefs_t;

/* XXX: I hate global variables */
static session_t    session;
static tpool_t      tpool;

static void signal_handler(int) __attribute__((noreturn));
static int  cleanup(session_t *, tpool_t *);
static void signal_handler(int);
static int  get_listener(prefs_t *);
static void set_defaults(prefs_t *);
static void print_usage(const char *program);


@@ 61,63 56,24 @@ static int  parse_prefs(int argc, char **argv, prefs_t *);
static void
signal_handler(int signum)
{
    printf("\n"
           "INFO : Received signal %i.\n"
           "     : Attempting a graceful shutdown...\n", signum);
    exit(cleanup(&session, &tpool));
}

static int
cleanup(session_t *sessionp, tpool_t *tpoolp)
{
    int     exit_code=EXIT_SUCCESS;
    char    err_str[STRERROR_BUFLEN];

    if ( pthread_rwlock_unlock(&sessionp->lock) ) {
        get_err_str(errno, err_str);
        fprintf(stderr, " ERR : %s:%i => `pthread_rwlock_unlock()`: %s\n",
                __FILE__, __LINE__ - 3, err_str);
        exit_code = EXIT_FAILURE;
    }

    printf("INFO : Destroying thread pool...\n");
    if ( tpool_destroy(tpoolp, 1) == -1 ) {
        fprintf(stderr, " ERR : %s:%i => `tpool_destroy()`: Failed to destroy"
                              " thread pool!\n"
                        "     : Watch out for those memory leaks!\n",
                __FILE__, __LINE__ - 4);
        exit_code = EXIT_FAILURE;
    }

    printf("INFO : Destroying session...\n");
    if ( session_destroy(sessionp) == -1 ) {
        fprintf(stderr, " ERR : %s:%i => `session_destroy()`: Failed to"
                              " destroy session!\n"
                        "     : Watch out for those memory leaks!\n",
                __FILE__, __LINE__ - 4);
        exit_code = EXIT_FAILURE;
    }

    return exit_code;
    printf("\nINFO : Received signal %i.\n", signum);
}

static int
get_listener(prefs_t *prefs)
{
    struct  addrinfo hints, *res, *p;
    int     status, listener=-1, yes;
    char    err_str[STRERROR_BUFLEN];

    /*
     * In order to set up a socket connection, we invoke the following
     * functions in this order:
     *
     *     1. getaddrinfo()
     *     2. socket()
     *     3. bind()
     *
     *  1. getaddrinfo()
     *  2. socket()
     *  3. bind()
     */

    struct  addrinfo hints, *res, *p;
    int     status, listener=-1, yes;
    char    err_str[STRERROR_BUFLEN];

    /*
     * `memset()` `hints` to zeroes, and set a few necessary fields.
     * This way `getaddrinfo()` will be able to set the other necessary


@@ 137,13 93,10 @@ get_listener(prefs_t *prefs)
        return -1;  /* We'd like to exit */
    }

    /*
     * `res` should now point to a linked list of addresses. In case
     * it's not:
     */
    /* res should now point to a linked list of addresses. In case it's not: */
    if ( !res ) {
        fprintf(stderr, " ERR : %s:%i => `getaddrinfo()` returned an empty"
                                       " list\n", __FILE__, __LINE__ - 10);
        fprintf(stderr, " ERR : %s:%i => `getaddrinfo()` returned an empty "
                                        "list\n", __FILE__, __LINE__ - 10);
        return -1;
    }



@@ 160,10 113,8 @@ get_listener(prefs_t *prefs)
        /* Try to get a socket file descriptor */
        if ( (listener = socket(p->ai_family, p->ai_socktype,
                                              p->ai_protocol)) == -1 )
            /*
             * We'll continue, perhaps the next address in the list
             * will succeed.
             */
            /* We'll continue, perhaps the next address in the list will
             * succeed */
            continue;

        /*


@@ 310,10 261,12 @@ print_usage_ret_error:
int
main(int argc, char **argv)
{
    int         listener, args_parsed, num_events;
    int         listener, args_parsed, num_events, exit_code;
    char        err_str[STRERROR_BUFLEN];
    struct      sigaction sa;
    prefs_t     prefs;
    session_t   session;
    tpool_t     tpool;

    /* Set up signal handler for ^C (SIGINT) TODO: and ^\ (SIGQUIT) */
    memset(&sa, 0, sizeof(struct sigaction));


@@ 358,12 311,17 @@ main(int argc, char **argv)
                             MAX_QUEUE_SZ, 0) ) {
        fprintf(stderr, " ERR : %s:%i => `tpool_init()`: Failed to initialize"
                              " thread pool!\n", __FILE__, __LINE__ - 3);
        goto destroy_session_and_exit_fail;
        exit_code = EXIT_FAILURE;
        goto destroy_session_and_exit;
    }

    printf("INFO : Initialized thread pool with %zu worker threads.\n",
                   tpool.num_threads);

    printf("INFO : Listening for connections on port %s\n", prefs.port);

    exit_code = EXIT_SUCCESS;   /* Let's hope for the best */

    /*
     * Now we gotta keep `poll()`ing and take care of everything
     * everytime `poll()` returns until the server receives a SIGINT.


@@ 373,17 331,25 @@ main(int argc, char **argv)
        get_err_str(errno, err_str);
        fprintf(stderr, " ERR : %s:%i => `pthread_rwlock_rdlock()`: %s\n",
                __FILE__, __LINE__ - 3, err_str);
        goto destroy_tpool_session_and_exit_fail;
        exit_code = EXIT_FAILURE;
        goto destroy_tpool_and_exit;
    }

    printf("INFO : Listening for connections on port %s\n", prefs.port);

    while ( 1 ) {
        if ( (num_events = poll(session.pfds,
                                (nfds_t) session.fd_count, -1)) == -1 ) {
            get_err_str(errno, err_str);
            fprintf(stderr, " ERR : %s:%i => `poll()`: %s\n",
                    __FILE__, __LINE__ - 11, err_str);
            if ( errno == EINTR ) {
                /*
                 * We got Ctrl-C'ed, we need to gracefully release any
                 * allocated memory in heap and then exit.
                 */
                printf("DBUG : `poll()` interrupted!\n");
            } else {
                get_err_str(errno, err_str);
                fprintf(stderr, " ERR : %s:%i => `poll()`: %s\n",
                        __FILE__, __LINE__ - 11, err_str);
                exit_code = EXIT_FAILURE;
            }
            break;  /* bail out */
        }



@@ 396,28 362,47 @@ main(int argc, char **argv)
            printf(" ERR : %s:%i => `process_events()`:"
                                  " Failed to handle events!\n",
                   __FILE__, __LINE__ - 3);
            exit_code = EXIT_FAILURE;
            break;  /* bail out */
        }
        printf("DBUG : All events handled!\n");
    }

    cleanup(&session, &tpool);
    goto exit_fail;
    if ( pthread_rwlock_unlock(&session.lock) ) {
        get_err_str(errno, err_str);
        fprintf(stderr, " ERR : %s:%i => `pthread_rwlock_unlock()`: %s\n",
                __FILE__, __LINE__ - 3, err_str);
        exit_code = EXIT_FAILURE;
        goto destroy_tpool_and_exit;
    }

    /*
     * ^C breaks `poll()` with EINTR which then we use to break the
     * outer infinite `while(1)` loop and hence we can finally reach
     * this code, do the necessary cleanup and exit gracefully.
     */

destroy_tpool_session_and_exit_fail:
    if ( tpool_destroy(&tpool, 1) == -1 )
    printf("INFO : Gracefully shutting down...\n");

destroy_tpool_and_exit:
    printf("INFO : Destroying thread pool...\n");
    if ( tpool_destroy(&tpool, 1) == -1 ) {
        fprintf(stderr, " ERR : %s:%i => `tpool_destroy()`: Failed to destroy"
                              " thread pool!\n"
                        "     : Watch out for those memory leaks!\n",
                __FILE__, __LINE__ - 4);
        exit_code = EXIT_FAILURE;
    }

destroy_session_and_exit_fail:
    if ( session_destroy(&session) == -1 )
destroy_session_and_exit:
    printf("INFO : Destroying session...\n");
    if ( session_destroy(&session) == -1 ) {
        fprintf(stderr, " ERR : %s:%i => `session_destroy()`: Failed to"
                              " destroy session!\n"
                        "     : Watch out for those memory leaks!\n",
                __FILE__, __LINE__ - 4);
        exit_code = EXIT_FAILURE;
    }

exit_fail:
    return EXIT_FAILURE;
    return exit_code;
}