Changeset 131d9a4 in mainline


Ignore:
Timestamp:
2012-09-07T07:56:01Z (12 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
70253688
Parents:
b6933f3
Message:

Logger: destroy logs on client disconnect

Location:
uspace/srv/logger
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/logger/initlvl.c

    rb6933f3 r131d9a4  
    6767
    6868        log->logged_level = level;
     69        log->ref_counter++;
    6970
    7071        log_unlock(log);
  • uspace/srv/logger/logger.h

    rb6933f3 r131d9a4  
    5858        link_t link;
    5959
     60        size_t ref_counter;
     61
    6062        fibril_mutex_t guard;
    6163
     
    6769};
    6870
     71#define MAX_REFERENCED_LOGS_PER_CLIENT 100
     72
     73typedef struct {
     74        size_t logs_count;
     75        logger_log_t *logs[MAX_REFERENCED_LOGS_PER_CLIENT];
     76} logger_registered_logs_t;
     77
    6978logger_log_t *find_log_by_name_and_lock(const char *name);
    7079logger_log_t *find_or_create_log_and_lock(const char *, sysarg_t);
     
    7382void log_unlock(logger_log_t *);
    7483void write_to_log(logger_log_t *, log_level_t, const char *);
     84void log_release(logger_log_t *);
     85
     86void registered_logs_init(logger_registered_logs_t *);
     87bool register_log(logger_registered_logs_t *, logger_log_t *);
     88void unregister_logs(logger_registered_logs_t *);
    7589
    7690log_level_t get_default_logging_level(void);
  • uspace/srv/logger/logs.c

    rb6933f3 r131d9a4  
    128128                        goto leave;
    129129                list_append(&result->link, &log_list);
     130                if (result->parent != NULL) {
     131                        fibril_mutex_lock(&result->parent->guard);
     132                        result->parent->ref_counter++;
     133                        fibril_mutex_unlock(&result->parent->guard);
     134                }
    130135        }
    131136
     
    200205}
    201206
     207/** Decreases reference counter on the log and destory the log if
     208 * necessary.
     209 *
     210 * Precondition: log is locked.
     211 *
     212 * @param log Log to release from using by the caller.
     213 */
     214void log_release(logger_log_t *log)
     215{
     216        assert(fibril_mutex_is_locked(&log->guard));
     217        assert(log->ref_counter > 0);
     218
     219        /* We are definitely not the last ones. */
     220        if (log->ref_counter > 1) {
     221                log->ref_counter--;
     222                fibril_mutex_unlock(&log->guard);
     223                return;
     224        }
     225
     226        /*
     227         * To prevent deadlock, we need to get the list lock first.
     228         * Deadlock scenario:
     229         * Us: LOCKED(log), want to LOCK(list)
     230         * Someone else calls find_log_by_name_and_lock(log->fullname) ->
     231         *   LOCKED(list), wants to LOCK(log)
     232         */
     233        fibril_mutex_unlock(&log->guard);
     234
     235        /* Ensuring correct locking order. */
     236        fibril_mutex_lock(&log_list_guard);
     237        /*
     238         * The reference must be still valid because we have not decreased
     239         * the reference counter.
     240         */
     241        fibril_mutex_lock(&log->guard);
     242        assert(log->ref_counter > 0);
     243        log->ref_counter--;
     244
     245        if (log->ref_counter > 0) {
     246                /*
     247                 * Meanwhile, someone else increased the ref counter.
     248                 * No big deal, we just return immediatelly.
     249                 */
     250                fibril_mutex_unlock(&log->guard);
     251                fibril_mutex_unlock(&log_list_guard);
     252                return;
     253        }
     254
     255        /*
     256         * Here we are on a destroy path. We need to
     257         * - remove ourselves from the list
     258         * - decrease reference of the parent (if not top-level log)
     259         *   - we must do that after we relaase list lock to prevent
     260         *     deadlock with ourselves
     261         * - destroy dest (if top-level log)
     262         */
     263        assert(log->ref_counter == 0);
     264
     265        list_remove(&log->link);
     266        fibril_mutex_unlock(&log_list_guard);
     267        fibril_mutex_unlock(&log->guard);
     268
     269        if (log->parent == NULL) {
     270                fclose(log->dest->logfile);
     271                free(log->dest->filename);
     272                free(log->dest);
     273        } else {
     274                fibril_mutex_lock(&log->parent->guard);
     275                log_release(log->parent);
     276        }
     277
     278        printf("Destroying log %s.\n", log->full_name);
     279
     280        free(log->name);
     281        free(log->full_name);
     282
     283        free(log);
     284}
     285
     286
    202287void write_to_log(logger_log_t *log, log_level_t level, const char *message)
    203288{
     
    218303}
    219304
     305void registered_logs_init(logger_registered_logs_t *logs)
     306{
     307        logs->logs_count = 0;
     308}
     309
     310bool register_log(logger_registered_logs_t *logs, logger_log_t *new_log)
     311{
     312        if (logs->logs_count >= MAX_REFERENCED_LOGS_PER_CLIENT) {
     313                return false;
     314        }
     315
     316        assert(fibril_mutex_is_locked(&new_log->guard));
     317        new_log->ref_counter++;
     318
     319        logs->logs[logs->logs_count] = new_log;
     320        logs->logs_count++;
     321
     322        return true;
     323}
     324
     325void unregister_logs(logger_registered_logs_t *logs)
     326{
     327        for (size_t i = 0; i < logs->logs_count; i++) {
     328                logger_log_t *log = logs->logs[i];
     329                fibril_mutex_lock(&log->guard);
     330                log_release(log);
     331        }
     332}
     333
    220334/**
    221335 * @}
  • uspace/srv/logger/writer.c

    rb6933f3 r131d9a4  
    100100        printf(NAME "/writer: new client.\n");
    101101
     102        logger_registered_logs_t registered_logs;
     103        registered_logs_init(&registered_logs);
     104
    102105        while (true) {
    103106                ipc_call_t call;
     
    112115                        if (log == NULL) {
    113116                                async_answer_0(callid, ENOMEM);
     117                                break;
     118                        }
     119                        if (!register_log(&registered_logs, log)) {
     120                                log_unlock(log);
     121                                async_answer_0(callid, ELIMIT);
    114122                                break;
    115123                        }
     
    130138        }
    131139
    132         // FIXME: destroy created logs
     140        unregister_logs(&registered_logs);
    133141}
    134142
Note: See TracChangeset for help on using the changeset viewer.