@@ -123,6 +123,15 @@ typedef struct _images_job_data_t
123123 gboolean overwrite ;
124124} _images_job_data_t ;
125125
126+ static _images_job_data_t * _dup_images_job_data_t (_images_job_data_t * data )
127+ {
128+ _images_job_data_t * d = g_malloc (sizeof (_images_job_data_t ));
129+ memcpy (d , data , sizeof (_images_job_data_t ));
130+ d -> imgs = g_list_copy (d -> imgs );
131+ d -> styles = g_list_copy (d -> styles );
132+ return d ;
133+ }
134+
126135static inline gboolean _job_cancelled (dt_job_t * job )
127136{
128137 return dt_control_job_get_state (job ) == DT_JOB_STATE_CANCELLED ;
@@ -248,9 +257,13 @@ static void _control_image_enumerator_cleanup(void *p)
248257
249258 g_list_free (params -> index );
250259 params -> index = NULL ;
251- //FIXME: we need to free params->data to avoid a memory leak, but
252- //doing so here causes memory corruption....
253- // g_free(params->data);
260+
261+ // we cannot free params->data as this is either a Glist * or an
262+ // allocated struct (_images_job_data_t). It is the responsibility
263+ // of the runner to free the data if needed. Furthermore, note that
264+ // some jobs are passing the images list to a signal which is turns
265+ // will free the list.
266+ params -> data = NULL ;
254267
255268 if (params -> blocking )
256269 g_main_context_invoke (NULL , _cursor_clear_busy , NULL );
@@ -1620,6 +1633,7 @@ static int32_t _control_paste_history_job_run(dt_job_t *job)
16201633 dt_collection_update_query (darktable .collection ,
16211634 DT_COLLECTION_CHANGE_RELOAD , DT_COLLECTION_PROP_UNDEF ,
16221635 (GList * )paste_data -> imgs ); // frees list of images
1636+
16231637 g_free (params -> data );
16241638 params -> data = NULL ;
16251639
@@ -2296,11 +2310,11 @@ void dt_control_refresh_exif()
22962310
22972311static void _add_history_job (GList * imgs ,
22982312 const char * title ,
2299- dt_job_execute_callback execute ,
2300- _images_job_data_t * images_job_data )
2313+ dt_job_execute_callback execute )
23012314{
23022315 if (!imgs || !execute )
23032316 return ;
2317+
23042318 GList * link = darktable .develop
23052319 ? g_list_find (imgs , GINT_TO_POINTER (darktable .develop -> image_storage .id ))
23062320 : NULL ;
@@ -2311,17 +2325,10 @@ static void _add_history_job(GList *imgs,
23112325 // images to be processed, and run it synchronously by itself
23122326 imgs = g_list_remove_link (imgs , link );
23132327
2314- if (images_job_data )
2315- images_job_data -> imgs = link ;
2316-
23172328 dt_control_add_job (DT_JOB_QUEUE_SYNCHRONOUS ,
23182329 _control_generic_images_job_create (execute , title , 0 ,
2319- images_job_data
2320- ? (gpointer )images_job_data
2321- : (gpointer )link ,
2330+ (gpointer )link ,
23222331 PROGRESS_BLOCKING , FALSE));
2323- if (images_job_data )
2324- images_job_data -> imgs = imgs ;
23252332 }
23262333 // if there are any images left in the list after removing the
23272334 // darkroom image, process them asynchronously but block user
@@ -2330,9 +2337,46 @@ static void _add_history_job(GList *imgs,
23302337 {
23312338 dt_control_add_job (DT_JOB_QUEUE_USER_FG ,
23322339 _control_generic_images_job_create (execute , title , 0 ,
2333- images_job_data
2334- ? (gpointer )images_job_data
2335- : (gpointer )imgs ,
2340+ (gpointer )imgs ,
2341+ PROGRESS_BLOCKING , FALSE));
2342+ }
2343+ }
2344+
2345+ static void _add_history_job_data (const char * title ,
2346+ dt_job_execute_callback execute ,
2347+ _images_job_data_t * images_job_data )
2348+ {
2349+ if (!images_job_data -> imgs || !execute )
2350+ return ;
2351+
2352+ GList * link = darktable .develop
2353+ ? g_list_find (images_job_data -> imgs ,
2354+ GINT_TO_POINTER (darktable .develop -> image_storage .id ))
2355+ : NULL ;
2356+
2357+ if (link )
2358+ {
2359+ // remove the image in darkroom center view from the list of
2360+ // images to be processed, and run it synchronously by itself
2361+ _images_job_data_t * d = _dup_images_job_data_t (images_job_data );
2362+ g_list_free (d -> imgs );
2363+ d -> imgs = link ;
2364+
2365+ images_job_data -> imgs = g_list_remove_link (images_job_data -> imgs , link );
2366+
2367+ dt_control_add_job (DT_JOB_QUEUE_SYNCHRONOUS ,
2368+ _control_generic_images_job_create (execute , title , 0 ,
2369+ (gpointer )d ,
2370+ PROGRESS_BLOCKING , FALSE));
2371+ }
2372+ // if there are any images left in the list after removing the
2373+ // darkroom image, process them asynchronously but block user
2374+ // interactions other than cancellation
2375+ if (images_job_data -> imgs )
2376+ {
2377+ dt_control_add_job (DT_JOB_QUEUE_USER_FG ,
2378+ _control_generic_images_job_create (execute , title , 0 ,
2379+ (gpointer )images_job_data ,
23362380 PROGRESS_BLOCKING , FALSE));
23372381 }
23382382}
@@ -2353,9 +2397,11 @@ void dt_control_paste_history(GList *imgs)
23532397 images_job_data -> duplicate = FALSE;
23542398 images_job_data -> overwrite = FALSE;
23552399
2356- _add_history_job ( imgs , N_ ("paste history" ),
2357- & _control_paste_history_job_run , images_job_data );
2400+ _add_history_job_data ( N_ ("paste history" ),
2401+ & _control_paste_history_job_run , images_job_data );
23582402 }
2403+ else
2404+ g_list_free (imgs );
23592405}
23602406
23612407void dt_control_paste_parts_history (GList * imgs )
@@ -2381,8 +2427,8 @@ void dt_control_paste_parts_history(GList *imgs)
23812427 images_job_data -> duplicate = FALSE;
23822428 images_job_data -> overwrite = darktable .view_manager -> copy_paste .is_overwrite_set ;
23832429
2384- _add_history_job ( imgs , N_ ("paste history" ),
2385- & _control_paste_history_job_run , images_job_data );
2430+ _add_history_job_data ( N_ ("paste history" ),
2431+ & _control_paste_history_job_run , images_job_data );
23862432 }
23872433 }
23882434 else
@@ -2395,9 +2441,10 @@ void dt_control_compress_history(GList *imgs)
23952441 {
23962442 (void )dt_history_compress (GPOINTER_TO_INT (imgs -> data ));
23972443 g_list_free (imgs );
2398- return ;
23992444 }
2400- _add_history_job (imgs , N_ ("compress history" ), & _control_compress_history_job_run , NULL );
2445+ else
2446+ _add_history_job (imgs , N_ ("compress history" ),
2447+ & _control_compress_history_job_run );
24012448}
24022449
24032450void dt_control_discard_history (GList * imgs )
@@ -2406,9 +2453,10 @@ void dt_control_discard_history(GList *imgs)
24062453 {
24072454 dt_history_delete (GPOINTER_TO_INT (imgs -> data ), TRUE);
24082455 g_list_free (imgs );
2409- return ;
24102456 }
2411- _add_history_job (imgs , N_ ("discard history" ), & _control_discard_history_job_run , NULL );
2457+ else
2458+ _add_history_job (imgs , N_ ("discard history" ),
2459+ & _control_discard_history_job_run );
24122460}
24132461
24142462void dt_control_apply_styles (GList * imgs , GList * styles , const gboolean duplicate )
0 commit comments