Commit 91ae35bb8c6418ccce439e9a1b42c1c5835b8850
1 parent
b8be8f94
Exists in
master
and in
1 other branch
Fixing memory leaks in FT Activity management.
Showing
6 changed files
with
112 additions
and
32 deletions
Show diff stats
src/filetransfer/activity.c
@@ -65,7 +65,7 @@ | @@ -65,7 +65,7 @@ | ||
65 | PROP_REMOTE | 65 | PROP_REMOTE |
66 | }; | 66 | }; |
67 | 67 | ||
68 | - G_DEFINE_TYPE(V3270FTActivity, V3270FTActivity, G_TYPE_OBJECT); | 68 | + G_DEFINE_TYPE(V3270FTActivity, V3270FTActivity, G_TYPE_INITIALLY_UNOWNED); |
69 | 69 | ||
70 | /*--[ Implement ]------------------------------------------------------------------------------------*/ | 70 | /*--[ Implement ]------------------------------------------------------------------------------------*/ |
71 | 71 | ||
@@ -148,16 +148,16 @@ | @@ -148,16 +148,16 @@ | ||
148 | return g_object_new(G_TYPE_V3270_FT_ACTIVITY, NULL); | 148 | return g_object_new(G_TYPE_V3270_FT_ACTIVITY, NULL); |
149 | } | 149 | } |
150 | 150 | ||
151 | - LIB3270_EXPORT const gchar * v3270_ft_activity_get_local_filename(GObject *object) | 151 | + LIB3270_EXPORT const gchar * v3270_ft_activity_get_local_filename(const GObject *object) |
152 | { | 152 | { |
153 | - gchar **ptr = & G_V3270_FT_ACTIVITY(object)->file.local; | ||
154 | - return(*ptr ? *ptr : ""); | 153 | + const gchar *ptr = G_V3270_FT_ACTIVITY(object)->file.local; |
154 | + return (ptr ? ptr : ""); | ||
155 | } | 155 | } |
156 | 156 | ||
157 | - LIB3270_EXPORT const gchar * v3270_ft_activity_get_remote_filename(GObject *object) | 157 | + LIB3270_EXPORT const gchar * v3270_ft_activity_get_remote_filename(const GObject *object) |
158 | { | 158 | { |
159 | - gchar **ptr = & G_V3270_FT_ACTIVITY(object)->file.remote; | ||
160 | - return(*ptr ? *ptr : ""); | 159 | + const gchar *ptr = G_V3270_FT_ACTIVITY(object)->file.remote; |
160 | + return(ptr ? ptr : ""); | ||
161 | } | 161 | } |
162 | 162 | ||
163 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename) | 163 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename) |
@@ -181,12 +181,12 @@ | @@ -181,12 +181,12 @@ | ||
181 | G_V3270_FT_ACTIVITY(object)->options = options; | 181 | G_V3270_FT_ACTIVITY(object)->options = options; |
182 | } | 182 | } |
183 | 183 | ||
184 | - LIB3270_EXPORT LIB3270_FT_OPTION v3270_ft_activity_get_options(GObject *object) | 184 | + LIB3270_EXPORT LIB3270_FT_OPTION v3270_ft_activity_get_options(const GObject *object) |
185 | { | 185 | { |
186 | return G_V3270_FT_ACTIVITY(object)->options; | 186 | return G_V3270_FT_ACTIVITY(object)->options; |
187 | } | 187 | } |
188 | 188 | ||
189 | - guint v3270_ft_activity_get_value(GObject * object, LIB3270_FT_VALUE id) | 189 | + guint v3270_ft_activity_get_value(const GObject * object, LIB3270_FT_VALUE id) |
190 | { | 190 | { |
191 | return G_V3270_FT_ACTIVITY(object)->values[id]; | 191 | return G_V3270_FT_ACTIVITY(object)->values[id]; |
192 | } | 192 | } |
src/filetransfer/activitylist.c
@@ -40,6 +40,11 @@ | @@ -40,6 +40,11 @@ | ||
40 | V3270_ACTIVITY_LIST_LAST_SIGNAL | 40 | V3270_ACTIVITY_LIST_LAST_SIGNAL |
41 | }; | 41 | }; |
42 | 42 | ||
43 | + typedef struct _activities | ||
44 | + { | ||
45 | + | ||
46 | + } Activities; | ||
47 | + | ||
43 | struct _V3270FTActivityListClass | 48 | struct _V3270FTActivityListClass |
44 | { | 49 | { |
45 | GtkTreeViewClass parent_class; | 50 | GtkTreeViewClass parent_class; |
@@ -65,14 +70,31 @@ | @@ -65,14 +70,31 @@ | ||
65 | 70 | ||
66 | static void dispose(GObject *object) | 71 | static void dispose(GObject *object) |
67 | { | 72 | { |
68 | - debug("%s",__FUNCTION__); | 73 | + debug("%s (model=%p)",__FUNCTION__,gtk_tree_view_get_model(GTK_TREE_VIEW(object))); |
69 | 74 | ||
70 | V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(object); | 75 | V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(object); |
71 | 76 | ||
77 | + // Release filename | ||
72 | debug("Freeing %s",list->filename); | 78 | debug("Freeing %s",list->filename); |
73 | g_free(list->filename); | 79 | g_free(list->filename); |
74 | list->filename = NULL; | 80 | list->filename = NULL; |
75 | 81 | ||
82 | + GtkTreeIter iter; | ||
83 | + GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(object)); | ||
84 | + | ||
85 | + while(model && gtk_tree_model_get_iter_first(model,&iter)) | ||
86 | + { | ||
87 | + GObject * activity = NULL; | ||
88 | + gtk_tree_model_get(model, &iter, 0, &activity, -1); | ||
89 | + | ||
90 | + gtk_list_store_remove(GTK_LIST_STORE(model),&iter); | ||
91 | + debug("Disposing activity %p",activity); | ||
92 | + | ||
93 | + g_clear_object(&activity); | ||
94 | + | ||
95 | + } | ||
96 | + | ||
97 | + | ||
76 | G_OBJECT_CLASS(V3270FTActivityList_parent_class)->dispose(object); | 98 | G_OBJECT_CLASS(V3270FTActivityList_parent_class)->dispose(object); |
77 | 99 | ||
78 | } | 100 | } |
@@ -118,7 +140,7 @@ | @@ -118,7 +140,7 @@ | ||
118 | 140 | ||
119 | static void V3270FTActivityList_init(V3270FTActivityList *widget) | 141 | static void V3270FTActivityList_init(V3270FTActivityList *widget) |
120 | { | 142 | { |
121 | - GtkTreeModel * model = GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_OBJECT)); | 143 | + GtkTreeModel * model = GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_POINTER)); // Using pointer type because I take care of refcounts. |
122 | 144 | ||
123 | widget->filename = NULL; | 145 | widget->filename = NULL; |
124 | 146 | ||
@@ -157,6 +179,8 @@ | @@ -157,6 +179,8 @@ | ||
157 | GtkTreeIter iter; | 179 | GtkTreeIter iter; |
158 | gtk_list_store_append((GtkListStore *) model,&iter); | 180 | gtk_list_store_append((GtkListStore *) model,&iter); |
159 | gtk_list_store_set((GtkListStore *) model, &iter, 0, activity, -1); | 181 | gtk_list_store_set((GtkListStore *) model, &iter, 0, activity, -1); |
182 | + g_object_ref_sink(activity); | ||
183 | + | ||
160 | } | 184 | } |
161 | 185 | ||
162 | void v3270_activity_list_remove(GtkWidget *widget, GObject *activity) | 186 | void v3270_activity_list_remove(GtkWidget *widget, GObject *activity) |
@@ -176,7 +200,9 @@ | @@ -176,7 +200,9 @@ | ||
176 | 200 | ||
177 | if(stored == activity) | 201 | if(stored == activity) |
178 | { | 202 | { |
203 | + debug("Removing activity %p",activity); | ||
179 | gtk_list_store_remove(GTK_LIST_STORE(model),&iter); | 204 | gtk_list_store_remove(GTK_LIST_STORE(model),&iter); |
205 | + g_object_unref(stored); | ||
180 | return; | 206 | return; |
181 | } | 207 | } |
182 | 208 |
src/filetransfer/dialog.c
@@ -155,6 +155,50 @@ static void begin_clicked(GtkButton G_GNUC_UNUSED(*button), V3270FTDialog *widge | @@ -155,6 +155,50 @@ static void begin_clicked(GtkButton G_GNUC_UNUSED(*button), V3270FTDialog *widge | ||
155 | gtk_dialog_response(GTK_DIALOG(widget),GTK_RESPONSE_ACCEPT); | 155 | gtk_dialog_response(GTK_DIALOG(widget),GTK_RESPONSE_ACCEPT); |
156 | } | 156 | } |
157 | 157 | ||
158 | +static gboolean v3270_activity_compare_filenames(const GObject *a, const GObject *b) | ||
159 | +{ | ||
160 | + if(strcmp(v3270_ft_activity_get_local_filename(a),v3270_ft_activity_get_local_filename(b))) | ||
161 | + return FALSE; | ||
162 | + | ||
163 | + if(strcmp(v3270_ft_activity_get_remote_filename(a),v3270_ft_activity_get_remote_filename(b))) | ||
164 | + return FALSE; | ||
165 | + | ||
166 | + return TRUE; | ||
167 | +} | ||
168 | + | ||
169 | +int v3270_ft_dialog_append_activity(GtkWidget *widget, GObject *activity, GError **error) | ||
170 | +{ | ||
171 | + V3270FTDialog *dialog = GTK_V3270_FT_DIALOG(widget); | ||
172 | + | ||
173 | + GtkTreeIter iter; | ||
174 | + GtkTreeModel * model = gtk_tree_view_get_model(GTK_TREE_VIEW(dialog->queue.view)); | ||
175 | + | ||
176 | + if(gtk_tree_model_get_iter_first(model,&iter)) | ||
177 | + { | ||
178 | + do | ||
179 | + { | ||
180 | + GObject * a = NULL; | ||
181 | + gtk_tree_model_get(model, &iter, 0, &a, -1); | ||
182 | + | ||
183 | + if(a && v3270_activity_compare_filenames(activity, a)) | ||
184 | + { | ||
185 | + // Activity already exist | ||
186 | + if(error && !*error) | ||
187 | + *error = g_error_new_literal(g_quark_from_static_string(PACKAGE_NAME),EPERM,_("Activity already on the queue")); | ||
188 | + | ||
189 | + return -1; | ||
190 | + } | ||
191 | + | ||
192 | + } | ||
193 | + while(gtk_tree_model_iter_next(model,&iter)); | ||
194 | + } | ||
195 | + | ||
196 | + // Not found, insert it. | ||
197 | + v3270_activity_list_append(dialog->queue.view,activity); | ||
198 | + | ||
199 | + return 0; | ||
200 | +} | ||
201 | + | ||
158 | static void insert_clicked(GtkWidget *button, V3270FTDialog *widget) | 202 | static void insert_clicked(GtkWidget *button, V3270FTDialog *widget) |
159 | { | 203 | { |
160 | GtkTreeIter iter; | 204 | GtkTreeIter iter; |
src/filetransfer/worker.c
@@ -131,11 +131,15 @@ | @@ -131,11 +131,15 @@ | ||
131 | pulse_stop(worker); | 131 | pulse_stop(worker); |
132 | timer_stop(worker); | 132 | timer_stop(worker); |
133 | 133 | ||
134 | + g_clear_object(&worker->activity); | ||
135 | + | ||
136 | + /* | ||
134 | if(worker->activity) | 137 | if(worker->activity) |
135 | { | 138 | { |
136 | g_object_unref(worker->activity); | 139 | g_object_unref(worker->activity); |
137 | worker->activity = NULL; | 140 | worker->activity = NULL; |
138 | } | 141 | } |
142 | + */ | ||
139 | 143 | ||
140 | G_OBJECT_CLASS(V3270FTWorker_parent_class)->finalize(object); | 144 | G_OBJECT_CLASS(V3270FTWorker_parent_class)->finalize(object); |
141 | 145 | ||
@@ -294,16 +298,12 @@ | @@ -294,16 +298,12 @@ | ||
294 | lib3270_ft_destroy(worker->hSession,NULL); | 298 | lib3270_ft_destroy(worker->hSession,NULL); |
295 | } | 299 | } |
296 | 300 | ||
297 | - if(worker->activity) | ||
298 | - { | ||
299 | - g_object_unref(worker->activity); | ||
300 | - worker->activity = NULL; | ||
301 | - } | 301 | + g_clear_object(&worker->activity); |
302 | 302 | ||
303 | if(activity) | 303 | if(activity) |
304 | { | 304 | { |
305 | worker->activity = activity; | 305 | worker->activity = activity; |
306 | - g_object_ref(worker->activity); | 306 | + g_object_ref_sink(activity); |
307 | 307 | ||
308 | gtk_entry_set_text(worker->field[PROGRESS_FIELD_LOCAL],v3270_ft_activity_get_local_filename(activity)); | 308 | gtk_entry_set_text(worker->field[PROGRESS_FIELD_LOCAL],v3270_ft_activity_get_local_filename(activity)); |
309 | gtk_entry_set_text(worker->field[PROGRESS_FIELD_REMOTE],v3270_ft_activity_get_remote_filename(activity)); | 309 | gtk_entry_set_text(worker->field[PROGRESS_FIELD_REMOTE],v3270_ft_activity_get_remote_filename(activity)); |
src/include/v3270/filetransfer.h
@@ -120,10 +120,10 @@ | @@ -120,10 +120,10 @@ | ||
120 | 120 | ||
121 | LIB3270_EXPORT void v3270_ft_activity_set_from_context(GObject * activity, GMarkupParseContext * context); | 121 | LIB3270_EXPORT void v3270_ft_activity_set_from_context(GObject * activity, GMarkupParseContext * context); |
122 | 122 | ||
123 | - LIB3270_EXPORT const gchar * v3270_ft_activity_get_local_filename(GObject *object); | ||
124 | - LIB3270_EXPORT const gchar * v3270_ft_activity_get_remote_filename(GObject *object); | ||
125 | - LIB3270_EXPORT LIB3270_FT_OPTION v3270_ft_activity_get_options(GObject *object); | ||
126 | - LIB3270_EXPORT guint v3270_ft_activity_get_value(GObject * object, LIB3270_FT_VALUE id); | 123 | + LIB3270_EXPORT const gchar * v3270_ft_activity_get_local_filename(const GObject *object); |
124 | + LIB3270_EXPORT const gchar * v3270_ft_activity_get_remote_filename(const GObject *object); | ||
125 | + LIB3270_EXPORT LIB3270_FT_OPTION v3270_ft_activity_get_options(const GObject *object); | ||
126 | + LIB3270_EXPORT guint v3270_ft_activity_get_value(const GObject * object, LIB3270_FT_VALUE id); | ||
127 | 127 | ||
128 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename); | 128 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename); |
129 | LIB3270_EXPORT void v3270_ft_activity_set_remote_filename(GObject *object, const gchar *filename); | 129 | LIB3270_EXPORT void v3270_ft_activity_set_remote_filename(GObject *object, const gchar *filename); |
@@ -144,6 +144,7 @@ | @@ -144,6 +144,7 @@ | ||
144 | 144 | ||
145 | LIB3270_EXPORT GtkWidget * v3270_ft_dialog_new(GtkWidget *parent); | 145 | LIB3270_EXPORT GtkWidget * v3270_ft_dialog_new(GtkWidget *parent); |
146 | LIB3270_EXPORT void v3270_ft_dialog_set_session(GtkWidget *widget, H3270 *hSession); | 146 | LIB3270_EXPORT void v3270_ft_dialog_set_session(GtkWidget *widget, H3270 *hSession); |
147 | + LIB3270_EXPORT int v3270_ft_dialog_append_activity(GtkWidget *widget, GObject *activity, GError **error); | ||
147 | 148 | ||
148 | G_END_DECLS | 149 | G_END_DECLS |
149 | 150 |
src/testprogram/testprogram.c
@@ -149,23 +149,32 @@ static void disconnect_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *term | @@ -149,23 +149,32 @@ static void disconnect_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *term | ||
149 | 149 | ||
150 | static void ft_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) | 150 | static void ft_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) |
151 | { | 151 | { |
152 | - GtkWidget * dialog = v3270_dialog_new(terminal, _("test"), _("test")); | ||
153 | - GtkWidget * worker = v3270_ft_worker_new(); | ||
154 | - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),worker,TRUE,TRUE,2); | ||
155 | - | ||
156 | - v3270_ft_worker_set_session(worker,v3270_get_session(terminal)); | ||
157 | - | 152 | + // |
153 | + // Test activity | ||
154 | + // | ||
158 | GObject * activity = v3270_ft_activity_new(); | 155 | GObject * activity = v3270_ft_activity_new(); |
156 | + debug("Activity %p is %s",activity,(g_object_is_floating(activity) ? "floating" : "non floating")); | ||
159 | v3270_ft_activity_set_local_filename(activity,"/tmp/test.txt"); | 157 | v3270_ft_activity_set_local_filename(activity,"/tmp/test.txt"); |
160 | v3270_ft_activity_set_remote_filename(activity,"remote_file"); | 158 | v3270_ft_activity_set_remote_filename(activity,"remote_file"); |
161 | v3270_ft_activity_set_options(activity,LIB3270_FT_OPTION_RECEIVE|LIB3270_FT_OPTION_ASCII|LIB3270_FT_OPTION_REMAP); | 159 | v3270_ft_activity_set_options(activity,LIB3270_FT_OPTION_RECEIVE|LIB3270_FT_OPTION_ASCII|LIB3270_FT_OPTION_REMAP); |
162 | - v3270_ft_worker_set_activity(worker,activity); | ||
163 | - g_object_unref(activity); | ||
164 | 160 | ||
165 | - v3270_ft_worker_start(worker); | 161 | + /* |
162 | + // | ||
163 | + // Test settings dialog | ||
164 | + // | ||
165 | + GtkWidget * dialog = v3270_ft_dialog_new(terminal); | ||
166 | + v3270_ft_dialog_append_activity(dialog,activity,NULL); | ||
167 | + */ | ||
166 | 168 | ||
167 | - // GtkWidget * dialog = v3270ftprogress_new(); | ||
168 | - // GtkWidget * dialog = v3270_ft_dialog_new(terminal); | 169 | + // |
170 | + // Test worker widget | ||
171 | + // | ||
172 | + GtkWidget * dialog = v3270_dialog_new(terminal, _("test"), _("test")); | ||
173 | + GtkWidget * worker = v3270_ft_worker_new(); | ||
174 | + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),worker,TRUE,TRUE,2); | ||
175 | + v3270_ft_worker_set_session(worker,v3270_get_session(terminal)); | ||
176 | + v3270_ft_worker_set_activity(worker,activity); | ||
177 | + v3270_ft_worker_start(worker); | ||
169 | 178 | ||
170 | gtk_widget_show_all(dialog); | 179 | gtk_widget_show_all(dialog); |
171 | gtk_dialog_run(GTK_DIALOG(dialog)); | 180 | gtk_dialog_run(GTK_DIALOG(dialog)); |