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 | 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 | 70 | /*--[ Implement ]------------------------------------------------------------------------------------*/ |
71 | 71 | |
... | ... | @@ -148,16 +148,16 @@ |
148 | 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 | 163 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename) |
... | ... | @@ -181,12 +181,12 @@ |
181 | 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 | 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 | 191 | return G_V3270_FT_ACTIVITY(object)->values[id]; |
192 | 192 | } | ... | ... |
src/filetransfer/activitylist.c
... | ... | @@ -40,6 +40,11 @@ |
40 | 40 | V3270_ACTIVITY_LIST_LAST_SIGNAL |
41 | 41 | }; |
42 | 42 | |
43 | + typedef struct _activities | |
44 | + { | |
45 | + | |
46 | + } Activities; | |
47 | + | |
43 | 48 | struct _V3270FTActivityListClass |
44 | 49 | { |
45 | 50 | GtkTreeViewClass parent_class; |
... | ... | @@ -65,14 +70,31 @@ |
65 | 70 | |
66 | 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 | 75 | V3270FTActivityList * list = GTK_V3270_FT_ACTIVITY_LIST(object); |
71 | 76 | |
77 | + // Release filename | |
72 | 78 | debug("Freeing %s",list->filename); |
73 | 79 | g_free(list->filename); |
74 | 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 | 98 | G_OBJECT_CLASS(V3270FTActivityList_parent_class)->dispose(object); |
77 | 99 | |
78 | 100 | } |
... | ... | @@ -118,7 +140,7 @@ |
118 | 140 | |
119 | 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 | 145 | widget->filename = NULL; |
124 | 146 | |
... | ... | @@ -157,6 +179,8 @@ |
157 | 179 | GtkTreeIter iter; |
158 | 180 | gtk_list_store_append((GtkListStore *) model,&iter); |
159 | 181 | gtk_list_store_set((GtkListStore *) model, &iter, 0, activity, -1); |
182 | + g_object_ref_sink(activity); | |
183 | + | |
160 | 184 | } |
161 | 185 | |
162 | 186 | void v3270_activity_list_remove(GtkWidget *widget, GObject *activity) |
... | ... | @@ -176,7 +200,9 @@ |
176 | 200 | |
177 | 201 | if(stored == activity) |
178 | 202 | { |
203 | + debug("Removing activity %p",activity); | |
179 | 204 | gtk_list_store_remove(GTK_LIST_STORE(model),&iter); |
205 | + g_object_unref(stored); | |
180 | 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 | 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 | 202 | static void insert_clicked(GtkWidget *button, V3270FTDialog *widget) |
159 | 203 | { |
160 | 204 | GtkTreeIter iter; | ... | ... |
src/filetransfer/worker.c
... | ... | @@ -131,11 +131,15 @@ |
131 | 131 | pulse_stop(worker); |
132 | 132 | timer_stop(worker); |
133 | 133 | |
134 | + g_clear_object(&worker->activity); | |
135 | + | |
136 | + /* | |
134 | 137 | if(worker->activity) |
135 | 138 | { |
136 | 139 | g_object_unref(worker->activity); |
137 | 140 | worker->activity = NULL; |
138 | 141 | } |
142 | + */ | |
139 | 143 | |
140 | 144 | G_OBJECT_CLASS(V3270FTWorker_parent_class)->finalize(object); |
141 | 145 | |
... | ... | @@ -294,16 +298,12 @@ |
294 | 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 | 303 | if(activity) |
304 | 304 | { |
305 | 305 | worker->activity = activity; |
306 | - g_object_ref(worker->activity); | |
306 | + g_object_ref_sink(activity); | |
307 | 307 | |
308 | 308 | gtk_entry_set_text(worker->field[PROGRESS_FIELD_LOCAL],v3270_ft_activity_get_local_filename(activity)); |
309 | 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 | 120 | |
121 | 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 | 128 | LIB3270_EXPORT void v3270_ft_activity_set_local_filename(GObject *object, const gchar *filename); |
129 | 129 | LIB3270_EXPORT void v3270_ft_activity_set_remote_filename(GObject *object, const gchar *filename); |
... | ... | @@ -144,6 +144,7 @@ |
144 | 144 | |
145 | 145 | LIB3270_EXPORT GtkWidget * v3270_ft_dialog_new(GtkWidget *parent); |
146 | 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 | 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 | 149 | |
150 | 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 | 155 | GObject * activity = v3270_ft_activity_new(); |
156 | + debug("Activity %p is %s",activity,(g_object_is_floating(activity) ? "floating" : "non floating")); | |
159 | 157 | v3270_ft_activity_set_local_filename(activity,"/tmp/test.txt"); |
160 | 158 | v3270_ft_activity_set_remote_filename(activity,"remote_file"); |
161 | 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 | 179 | gtk_widget_show_all(dialog); |
171 | 180 | gtk_dialog_run(GTK_DIALOG(dialog)); | ... | ... |