Commit 91ae35bb8c6418ccce439e9a1b42c1c5835b8850

Authored by Perry Werneck
1 parent b8be8f94
Exists in master and in 1 other branch develop

Fixing memory leaks in FT Activity management.

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));
... ...