all repos — tint2 @ 66cae4bb7c46a0a68b01892381f24f87db8546a7

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Fix dangling pointers causing erratic timer behaviour (affects taskbar with spacing); use calloc instead of malloc for safer initializations

git-svn-id: http://tint2.googlecode.com/svn/trunk@758 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
o9000 o9000
commit

66cae4bb7c46a0a68b01892381f24f87db8546a7

parent

778b9f0ebfd0cb2e9f5f8e664e0eca4b24e5d9d4

M sample/tint2rcsample/tint2rc

@@ -2,26 +2,38 @@ # Tint2 sample config file

# For information on manually configuring tint2 see http://code.google.com/p/tint2/wiki/Configure # Background definitions -# ID 1 +# Background 1: panel rounded = 7 -border_width = 2 +border_width = 1 background_color = #000000 60 border_color = #FFFFFF 16 -# ID 2 +# Background 2: normal/iconified tasks rounded = 5 border_width = 0 -background_color = #777777 40 -border_color = #FFFFFF 48 +background_color = #777777 20 +border_color = #777777 30 + +# Background 3: active tasks +rounded = 5 +border_width = 1 +background_color = #777777 20 +border_color = #ffffff 40 -# ID 3 +# Background 4: urgent tasks rounded = 5 border_width = 1 -background_color = #777777 40 -border_color = #FFFFFF 60 +background_color = #aa4400 100 +border_color = #aa7733 100 + +# Background 5: tooltips +rounded = 2 +border_width = 1 +background_color = #ffffaa 100 +border_color = #999999 100 # Panel -panel_items = LTSC +panel_items = LTSBC panel_monitor = all panel_position = bottom center horizontal panel_size = 95% 30

@@ -34,8 +46,8 @@ panel_background_id = 1

# Panel Autohide autohide = 0 -autohide_show_timeout = 0.3 -autohide_hide_timeout = 2 +autohide_show_timeout = 0 +autohide_hide_timeout = 0.5 autohide_height = 2 strut_policy = follow_size

@@ -63,13 +75,13 @@ task_maximum_size = 140 35

task_padding = 6 2 task_background_id = 2 task_active_background_id = 3 -task_urgent_background_id = 2 +task_urgent_background_id = 4 task_iconified_background_id = 2 -task_tooltip = 0 +task_tooltip = 1 urgent_nb_of_blink = 100000 # Task Icons -task_icon_asb = 80 0 0 +task_icon_asb = 100 0 0 task_active_icon_asb = 100 0 0 task_urgent_icon_asb = 100 0 0 task_iconified_icon_asb = 70 0 0

@@ -86,8 +98,8 @@ # Mouse

mouse_left = toggle_iconify mouse_middle = none mouse_right = close -mouse_scroll_up = toggle -mouse_scroll_down = iconify +mouse_scroll_up = prev_task +mouse_scroll_down = next_task # System Tray systray_padding = 0 4 5

@@ -101,18 +113,18 @@ time1_format = %H:%M

time1_font = sans 8 time2_format = %A %d %B time2_font = sans 7 -clock_font_color = #FFFFFF 74 +clock_font_color = #FFFFFF 90 clock_padding = 1 0 clock_background_id = 0 clock_rclick_command = orage # Tooltips tooltip_padding = 2 2 -tooltip_show_timeout = 0.7 -tooltip_hide_timeout = 0.3 -tooltip_background_id = 1 -tooltip_font = sans 10 -tooltip_font_color = #000000 80 +tooltip_show_timeout = 0.5 +tooltip_hide_timeout = 0.1 +tooltip_background_id = 5 +tooltip_font = sans 9 +tooltip_font_color = #222222 100 # Battery battery_low_status = 10

@@ -120,7 +132,7 @@ battery_low_cmd = notify-send "battery low"

battery_hide = 98 bat1_font = sans 8 bat2_font = sans 6 -battery_font_color = #FFFFFF 74 +battery_font_color = #FFFFFF 94 battery_padding = 1 0 battery_background_id = 0
M src/battery/battery.csrc/battery/battery.c

@@ -274,9 +274,8 @@ fprintf(stderr, "ERROR: battery applet cannot find any batteries\n");

} #endif - if (battery_timeout == 0) { - battery_timeout = add_timeout(10, 10000, update_battery_tick, 0); - } + if (!battery_timeout) + battery_timeout = add_timeout(10, 10000, update_battery_tick, 0, &battery_timeout); }
M src/clock/clock.csrc/clock/clock.c

@@ -152,9 +152,9 @@ {

if (!clock_timeout) { if (time_format_needs_sec_ticks(time1_format) || time_format_needs_sec_ticks(time2_format)) { - clock_timeout = add_timeout(10, 1000, update_clocks_sec, 0); + clock_timeout = add_timeout(10, 1000, update_clocks_sec, 0, &clock_timeout); } else { - clock_timeout = add_timeout(10, 1000, update_clocks_min, 0); + clock_timeout = add_timeout(10, 1000, update_clocks_min, 0, &clock_timeout); } } }
M src/launcher/apps-common.csrc/launcher/apps-common.c

@@ -52,7 +52,7 @@ // %i -> --icon Icon

// %c -> Name // %k -> path if (entry->exec) { - char *exec2 = malloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) + (entry->icon ? strlen(entry->icon) : 1) + 100); + char *exec2 = calloc(strlen(entry->exec) + (entry->name ? strlen(entry->name) : 1) + (entry->icon ? strlen(entry->icon) : 1) + 100, 1); char *p, *q; // p will never point to an escaped char for (p = entry->exec, q = exec2; *p; p++, q++) {
M src/launcher/icon-theme-common.csrc/launcher/icon-theme-common.c

@@ -561,8 +561,8 @@ char *base_name = (char*) base->data;

char *theme_name = ((IconTheme*)theme->data)->name; char *dir_name = ((IconThemeDir*)dir->data)->name; char *extension = (char*) ext->data; - char *file_name = malloc(strlen(base_name) + strlen(theme_name) + - strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100); + char *file_name = calloc(strlen(base_name) + strlen(theme_name) + + strlen(dir_name) + strlen(icon_name) + strlen(extension) + 100, 1); // filename = directory/$(themename)/subdirectory/iconname.extension sprintf(file_name, "%s/%s/%s/%s%s", base_name, theme_name, dir_name, icon_name, extension); if (DEBUG_ICON_SEARCH)

@@ -620,8 +620,8 @@ GSList *ext;

for (ext = extensions; ext; ext = g_slist_next(ext)) { char *base_name = (char*) base->data; char *extension = (char*) ext->data; - char *file_name = malloc(strlen(base_name) + strlen(icon_name) + - strlen(extension) + 100); + char *file_name = calloc(strlen(base_name) + strlen(icon_name) + + strlen(extension) + 100, 1); // filename = directory/iconname.extension sprintf(file_name, "%s/%s%s", base_name, icon_name, extension); if (DEBUG_ICON_SEARCH)
M src/launcher/launcher.csrc/launcher/launcher.c

@@ -391,7 +391,7 @@ }

void launcher_action(LauncherIcon *icon, XEvent* evt) { - char *cmd = malloc(strlen(icon->cmd) + 10); + char *cmd = calloc(strlen(icon->cmd) + 10, 1); sprintf(cmd, "(%s&)", icon->cmd); #if HAVE_SN SnLauncherContext* ctx;
M src/launcher/xsettings-client.csrc/launcher/xsettings-client.c

@@ -235,14 +235,14 @@ result = XSETTINGS_ACCESS;

goto out; } - setting = malloc (sizeof *setting); + setting = calloc (1, sizeof *setting); if (!setting) { result = XSETTINGS_NO_MEM; goto out; } setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */ - setting->name = malloc (name_len + 1); + setting->name = calloc (name_len + 1, 1); if (!setting->name) { result = XSETTINGS_NO_MEM; goto out;

@@ -276,7 +276,7 @@ result = XSETTINGS_ACCESS;

goto out; } - setting->data.v_string = malloc (v_int + 1); + setting->data.v_string = calloc (v_int + 1, 1); if (!setting->data.v_string) { result = XSETTINGS_NO_MEM; goto out;

@@ -400,7 +400,7 @@ XSettingsClient *xsettings_client_new (Display *display, int screen, XSettingsNotifyFunc notify, XSettingsWatchFunc watch, void *cb_data)

{ XSettingsClient *client; - client = malloc (sizeof *client); + client = calloc (1, sizeof *client); if (!client) return NULL;
M src/launcher/xsettings-common.csrc/launcher/xsettings-common.c

@@ -34,12 +34,12 @@ {

XSettingsSetting *result; size_t str_len; - result = malloc (sizeof *result); + result = calloc (1, sizeof *result); if (!result) return NULL; str_len = strlen (setting->name); - result->name = malloc (str_len + 1); + result->name = calloc (str_len + 1, 1); if (!result->name) goto err;

@@ -57,7 +57,7 @@ result->data.v_color = setting->data.v_color;

break; case XSETTINGS_TYPE_STRING: str_len = strlen (setting->data.v_string); - result->data.v_string = malloc (str_len + 1); + result->data.v_string = calloc (str_len + 1, 1); if (!result->data.v_string) goto err;

@@ -90,7 +90,7 @@ while (old_iter)

{ XSettingsList *new_node; - new_node = malloc (sizeof *new_node); + new_node = calloc (1, sizeof *new_node); if (!new_node) goto error;

@@ -180,7 +180,7 @@ XSettingsList *node;

XSettingsList *iter; XSettingsList *last = NULL; - node = malloc (sizeof *node); + node = calloc (1, sizeof *node); if (!node) return XSETTINGS_NO_MEM; node->setting = setting;
M src/panel.csrc/panel.c

@@ -126,6 +126,7 @@ p->hidden_pixmap = 0;

if (p->main_win) XDestroyWindow(server.dsp, p->main_win); p->main_win = 0; + stop_timeout(p->autohide_timeout); } free(panel_items_order);

@@ -167,7 +168,7 @@ nb_panel = 1;

else nb_panel = server.nb_monitor; - panel1 = malloc(nb_panel * sizeof(Panel)); + panel1 = calloc(nb_panel, sizeof(Panel)); for (i=0 ; i < nb_panel ; i++) { memcpy(&panel1[i], &panel_config, sizeof(Panel)); }

@@ -231,7 +232,7 @@ XMapWindow (server.dsp, p->main_win);

} if (panel_autohide) - add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p); + autohide_trigger_hide(p); visible_taskbar(p); }

@@ -811,10 +812,7 @@

void stop_autohide_timeout(Panel* p) { - if (p->autohide_timeout) { - stop_timeout(p->autohide_timeout); - p->autohide_timeout = 0; - } + stop_timeout(p->autohide_timeout); }

@@ -875,10 +873,7 @@ void autohide_trigger_show(Panel* p)

{ if (!p) return; - if (p->autohide_timeout) - change_timeout(p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p); - else - p->autohide_timeout = add_timeout(panel_autohide_show_timeout, 0, autohide_show, p); + change_timeout(&p->autohide_timeout, panel_autohide_show_timeout, 0, autohide_show, p); }

@@ -893,8 +888,5 @@ unsigned int mask;

if (XQueryPointer(server.dsp, p->main_win, &root, &child, &xr, &yr, &xw, &yw, &mask)) if (child) return; // mouse over one of the system tray icons - if (p->autohide_timeout) - change_timeout(p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p); - else - p->autohide_timeout = add_timeout(panel_autohide_hide_timeout, 0, autohide_hide, p); + change_timeout(&p->autohide_timeout, panel_autohide_hide_timeout, 0, autohide_hide, p); }
M src/server.csrc/server.c

@@ -295,14 +295,14 @@ XRRFreeCrtcInfo(crtc_info);

} printf("xRandr: Found crtc's: %d\n", res->ncrtc ); - server.monitor = malloc(res->ncrtc * sizeof(Monitor)); + server.monitor = calloc(res->ncrtc, sizeof(Monitor)); for (i=0; i<res->ncrtc; ++i) { XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(server.dsp, res, res->crtcs[i]); server.monitor[i].x = crtc_info->x; server.monitor[i].y = crtc_info->y; server.monitor[i].width = crtc_info->width; server.monitor[i].height = crtc_info->height; - server.monitor[i].names = malloc((crtc_info->noutput+1) * sizeof(gchar*)); + server.monitor[i].names = calloc((crtc_info->noutput+1), sizeof(gchar*)); for (j=0; j<crtc_info->noutput; ++j) { XRROutputInfo* output_info = XRRGetOutputInfo(server.dsp, res, crtc_info->outputs[j]); printf("xRandr: Linking output %s with crtc %d\n", output_info->name, i);

@@ -315,7 +315,7 @@ }

nbmonitor = res->ncrtc; } else if (info && nbmonitor > 0) { - server.monitor = malloc(nbmonitor * sizeof(Monitor)); + server.monitor = calloc(nbmonitor, sizeof(Monitor)); for (i=0 ; i < nbmonitor ; i++) { server.monitor[i].x = info[i].x_org; server.monitor[i].y = info[i].y_org;

@@ -353,7 +353,7 @@ }

if (!server.nb_monitor) { server.nb_monitor = 1; - server.monitor = malloc(sizeof(Monitor)); + server.monitor = calloc(1, sizeof(Monitor)); server.monitor[0].x = server.monitor[0].y = 0; server.monitor[0].width = DisplayWidth (server.dsp, server.screen); server.monitor[0].height = DisplayHeight (server.dsp, server.screen);
M src/systray/systraybar.csrc/systray/systraybar.c

@@ -496,8 +496,7 @@ XReparentWindow(server.dsp, traywin->tray_id, server.root_win, 0, 0);

XDestroyWindow(server.dsp, traywin->id); XSync(server.dsp, False); XSetErrorHandler(old); - if (traywin->render_timeout) - stop_timeout(traywin->render_timeout); + stop_timeout(traywin->render_timeout); g_free(traywin); // check empty systray

@@ -619,8 +618,8 @@ void systray_render_icon(TrayWindow* traywin)

{ if (FORCE_COMPOSITED_RENDERING || server.real_transparency || systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) { // wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms - if (traywin->render_timeout == 0) - traywin->render_timeout = add_timeout(50, 0, systray_render_icon_now, traywin); + if (!traywin->render_timeout) + traywin->render_timeout = add_timeout(50, 0, systray_render_icon_now, traywin, &traywin->render_timeout); } else { // Pixmap pix = XCreatePixmap(server.dsp, server.root_win, traywin->width, traywin->height, server.depth);
M src/taskbar/task.csrc/taskbar/task.c

@@ -87,7 +87,7 @@ for (j=0 ; j < panel1[monitor].nb_desktop ; j++) {

if (new_tsk.desktop != ALLDESKTOP && new_tsk.desktop != j) continue; tskbar = &panel1[monitor].taskbar[j]; - new_tsk2 = malloc(sizeof(Task)); + new_tsk2 = calloc(1, sizeof(Task)); memcpy(&new_tsk2->area, &panel1[monitor].g_task.area, sizeof(Area)); new_tsk2->area.parent = tskbar; new_tsk2->win = new_tsk.win;

@@ -115,7 +115,7 @@ tskbar->area.resize = 1;

g_ptr_array_add(task_group, new_tsk2); //printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title); } - Window* key = malloc(sizeof(Window)); + Window* key = calloc(1, sizeof(Window)); *key = new_tsk.win; g_hash_table_insert(win_to_task_table, key, task_group); set_task_state(new_tsk2, new_tsk.current_state);

@@ -195,14 +195,14 @@ name = server_get_property (tsk->win, server.atom._NET_WM_NAME, server.atom.UTF8_STRING, 0);

if (!name || !strlen(name)) { name = server_get_property (tsk->win, server.atom.WM_NAME, XA_STRING, 0); if (!name || !strlen(name)) { - name = malloc(10); + name = calloc(10, 1); strcpy(name, "Untitled"); } } } // add space before title - title = malloc(strlen(name)+2); + title = calloc(strlen(name)+2, 1); if (panel->g_task.icon) strcpy(title, " "); else title[0] = 0; strcat(title, name);

@@ -620,7 +620,7 @@ // not yet in the list, so we have to add it

urgent_list = g_slist_prepend(urgent_list, tsk); if (!urgent_timeout) - urgent_timeout = add_timeout(10, 1000, blink_urgent, 0); + urgent_timeout = add_timeout(10, 1000, blink_urgent, 0, &urgent_timeout); Panel *panel = tsk->area.panel; if (panel->is_hidden)
M src/taskbar/taskbar.csrc/taskbar/taskbar.c

@@ -109,7 +109,6 @@ g_slist_free(urgent_list);

urgent_list = NULL; stop_timeout(urgent_timeout); - urgent_timeout = NULL; }
M src/tint.csrc/tint.c

@@ -1350,7 +1350,7 @@ cmd_length += 1; // close double quotes

cmd_length += 2; // &) cmd_length += 1; // terminator - char *cmd = malloc(cmd_length); + char *cmd = calloc(cmd_length, 1); cmd[0] = '\0'; strcat(cmd, "("); strcat(cmd, dnd_launcher_exec);
M src/tooltip/tooltip.csrc/tooltip/tooltip.c

@@ -86,7 +86,7 @@

void tooltip_trigger_show(Area* area, Panel* p, XEvent *e) { // Position the tooltip in the center of the area - x = area->posx + area->width / 2 + e->xmotion.x_root - e->xmotion.x; + x = area->posx + MIN(area->width / 3, 22) + e->xmotion.x_root - e->xmotion.x; y = area->posy + area->height / 2 + e->xmotion.y_root - e->xmotion.y; just_shown = 1; g_tooltip.panel = p;

@@ -108,7 +108,6 @@ Window w;

XTranslateCoordinates( server.dsp, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w); Area* area; area = click_area(g_tooltip.panel, mx, my); - stop_tooltip_timeout(); if (!g_tooltip.mapped && area->_get_tooltip_text) { tooltip_copy_text(area); g_tooltip.mapped = True;

@@ -275,7 +274,6 @@

void tooltip_hide(void* arg) { - stop_tooltip_timeout(); if (g_tooltip.mapped) { g_tooltip.mapped = False; XUnmapWindow(server.dsp, g_tooltip.window);

@@ -286,26 +284,19 @@

void start_show_timeout() { - if (g_tooltip.timeout) - change_timeout(g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0); - else - g_tooltip.timeout = add_timeout(g_tooltip.show_timeout_msec, 0, tooltip_show, 0); + change_timeout(&g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show, 0); } void start_hide_timeout() { - if (g_tooltip.timeout) - change_timeout(g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0); - else - g_tooltip.timeout = add_timeout(g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0); + change_timeout(&g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide, 0); } void stop_tooltip_timeout() { stop_timeout(g_tooltip.timeout); - g_tooltip.timeout = NULL; }
M src/util/timer.csrc/util/timer.c

@@ -44,6 +44,7 @@ struct timespec timeout_expires;

void (*_callback)(void*); void* arg; multi_timeout* multi_timeout; + timeout **self; }; void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(void*), void* arg, timeout* t);

@@ -74,6 +75,8 @@ while (timeout_list) {

timeout* t = timeout_list->data; if (t->multi_timeout) stop_multi_timeout(t); + if (t->self) + *t->self = NULL; free(t); timeout_list = g_slist_remove(timeout_list, t); }

@@ -95,25 +98,26 @@ * of add_timeout will not be valid anymore. You do not need to call stop_timeout for these timeouts,

* however it's save to call it. **/ -timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg) +timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg, timeout **self) { - timeout* t = malloc(sizeof(timeout)); - t->multi_timeout = 0; + timeout* t = calloc(1, sizeof(timeout)); + t->self = self; add_timeout_intern(value_msec, interval_msec, _callback, arg, t); return t; } -void change_timeout(timeout *t, int value_msec, int interval_msec, void(*_callback)(), void* arg) +void change_timeout(timeout **t, int value_msec, int interval_msec, void(*_callback)(), void* arg) { - if ( g_slist_find(timeout_list, t) == 0 && g_hash_table_lookup(multi_timeouts, t) == 0) - printf("programming error: timeout already deleted..."); + if (!((timeout_list && g_slist_find(timeout_list, *t)) || + (multi_timeouts && g_hash_table_lookup(multi_timeouts, *t)))) + *t = add_timeout(value_msec, interval_msec, _callback, arg, t); else { - if (t->multi_timeout) - remove_from_multi_timeout((timeout*)t); + if ((*t)->multi_timeout) + remove_from_multi_timeout(*t); else - timeout_list = g_slist_remove(timeout_list, t); - add_timeout_intern(value_msec, interval_msec, _callback, arg, (timeout*)t); + timeout_list = g_slist_remove(timeout_list, *t); + add_timeout_intern(value_msec, interval_msec, _callback, arg, *t); } }

@@ -149,31 +153,40 @@ t = timeout_list->data;

if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) { // it's time for the callback function t->_callback(t->arg); + // If _callback() calls stop_timeout(t) the timer 't' was freed and is not in the timeout_list if (g_slist_find(timeout_list, t)) { - // if _callback() calls stop_timeout(t) the timeout 't' was freed and is not in the timeout_list + // Timer still exists timeout_list = g_slist_remove(timeout_list, t); - if (t->interval_msec > 0) + if (t->interval_msec > 0) { add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t->arg, t); - else + } else { + // Destroy single-shot timer + if (t->self) + *t->self = NULL; free(t); + } } - } - else + } else { return; + } } } void stop_timeout(timeout* t) { - if (!multi_timeouts || !t) + if (!t) return; // if not in the list, it was deleted in callback_timeout_expired - if (g_slist_find(timeout_list, t) || g_hash_table_lookup(multi_timeouts, t)) { - if (t->multi_timeout) - remove_from_multi_timeout((timeout*)t); - timeout_list = g_slist_remove(timeout_list, t); - free((void*)t); + if ((timeout_list && g_slist_find(timeout_list, t)) || + (multi_timeouts && g_hash_table_lookup(multi_timeouts, t))) { + if (multi_timeouts && t->multi_timeout) + remove_from_multi_timeout(t); + if (timeout_list) + timeout_list = g_slist_remove(timeout_list, t); + if (t->self) + *t->self = NULL; + free(t); } }

@@ -198,7 +211,7 @@

gint compare_timeouts(gconstpointer t1, gconstpointer t2) { return compare_timespecs(&((timeout*)t1)->timeout_expires, - &((timeout*)t2)->timeout_expires); + &((timeout*)t2)->timeout_expires); }

@@ -262,12 +275,13 @@ if (t2->interval_msec > 0) {

if (t->interval_msec % t2->interval_msec == 0 || t2->interval_msec % t->interval_msec == 0) { if (multi_timeouts == 0) multi_timeouts = g_hash_table_new(0, 0); - if (!t->multi_timeout && !t2->multi_timeout) + if (!t->multi_timeout && !t2->multi_timeout) { // both timeouts can be aligned, but there is no multi timeout for them create_multi_timeout(t, t2); - else + } else { // there is already a multi timeout, so we append the new timeout to the multi timeout append_multi_timeout(t, t2); + } return 1; } }

@@ -295,10 +309,10 @@

void create_multi_timeout(timeout* t1, timeout* t2) { - multi_timeout* mt1 = malloc(sizeof(multi_timeout)); - multi_timeout* mt2 = malloc(sizeof(multi_timeout)); - multi_timeout_handler* mth = malloc(sizeof(multi_timeout_handler)); - timeout* real_timeout = malloc(sizeof(timeout)); + multi_timeout* mt1 = calloc(1, sizeof(multi_timeout)); + multi_timeout* mt2 = calloc(1, sizeof(multi_timeout)); + multi_timeout_handler* mth = calloc(1, sizeof(multi_timeout_handler)); + timeout* real_timeout = calloc(1, sizeof(timeout)); mth->timeout_list = 0; mth->timeout_list = g_slist_prepend(mth->timeout_list, t1);

@@ -331,7 +345,7 @@ t2 = t1;

t1 = tmp; } - multi_timeout* mt = malloc(sizeof(multi_timeout)); + multi_timeout* mt = calloc(1, sizeof(multi_timeout)); multi_timeout_handler* mth = g_hash_table_lookup(multi_timeouts, t1); mth->timeout_list = g_slist_prepend(mth->timeout_list, t2);
M src/util/timer.hsrc/util/timer.h

@@ -21,7 +21,6 @@ #define TIMER_H

#include <glib.h> -extern GSList* timeout_list; extern struct timeval next_timeout;

@@ -30,26 +29,33 @@

// timer functions /** - * Single shot timer (i.e. timer with interval_msec == 0) are deleted automatically as soon as they expire + * Single shot timers (i.e. timers with interval_msec == 0) are deleted automatically as soon as they expire, * i.e. you do not need to stop them, however it is safe to call stop_timeout for these timers. + * You can pass the address of the variable storing the pointer to the timer as 'self' in add_timeout, in which + * case it is used to clear the pointer if the timer is destroyed automatically. This enforces the timeout pointers + * to be either valid or NULL. * Periodic timeouts are aligned to each other whenever possible, i.e. one interval_msec is an * integral multiple of the other. **/ -/** default global data **/ +/** Initializes default global data. **/ void default_timeout(); -/** freed memory : stops all timeouts **/ +/** Cleans up: stops all timers and frees memory. **/ void cleanup_timeout(); -/** installs a timeout with the first timeout of 'value_msec' and then a periodic timeout with - * 'interval_msec'. '_callback' is the callback function when the timer reaches the timeout. - * returns a pointer to the timeout, which is needed for stopping it again +/** Installs a timer with the first timeout after 'value_msec' and then an optional periodic timeout every + * 'interval_msec' (set it to 0 to prevent periodic timeouts). + * '_callback' is the function called when the timer reaches the timeout. + * 'arg' is the argument passed to the callback function. + * 'self' is an optional pointer to a timeout* variable. If non-NULL, the variable is set to NULL when the timer + * is destroyed (with stop_timeout, cleanup_timeout or when the timer expires and it is single-shot). + * Returns a pointer to the timer, which is needed for stopping/changing it. **/ -timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg); +timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)(void*), void* arg, timeout **self); -/** changes timeout 't'. If timeout 't' does not exist, nothing happens **/ -void change_timeout(timeout* t, int value_msec, int interval_msec, void (*_callback)(void*), void* arg); +/** Changes timer 't'. If it does not exist, a new timer is created, with self set to 't'. **/ +void change_timeout(timeout** t, int value_msec, int interval_msec, void (*_callback)(void*), void* arg); /** stops the timeout 't' **/ void stop_timeout(timeout* t);