[fprint] Memory management Libfprint

Carlos Garcia gavajc at live.com
Tue Apr 20 23:09:50 UTC 2021


Hi everyone. I have some questions with the memory management with libfprint.
I’m creating a program for capture image and retrieve the minutiae from the captured image. I’m using:


  *   fp_device_capture
  *   fp_device_capture_finish
  *   fp_image_detect_minutiae
  *   fp_image_detect_minutiae_finish

I have relied on the img-capture.c example from the version 1.90.7 examples.
Here is my code:

///< This function is executed in another thread using pthreads
static void * etr_fp_gmain_loop(void *data)
{
    FpContext *context   = NULL;
    tAUTOMATON_DATA *aut = (tAUTOMATON_DATA *) data;
    aut->ctx.clops  = g_cancellable_new();

    // Create libfprint context

    if ((context = etr_fp_find_device(aut)) != NULL) // Inside this function open device with fp_device_open_sync
    {
        KernelInsertEvent(aut->fsm->aut_id,AUT_EVT_OPENED,NULL,0);
        aut->ctx.gmloop = g_main_loop_new(NULL,FALSE);
        g_main_loop_run(aut->ctx.gmloop);    // Run until g_main_loop_quit is called.

        // Free resources.
        g_main_loop_unref(aut->ctx.gmloop);
        g_clear_object(&context);
        aut->ctx.device = NULL;
        aut->ctx.gmloop = NULL;
    }

    g_clear_object(&aut->ctx.clops); // Free GCancellable.

    return NULL;
}
//---------------------------------------------------------------------------

static void etr_fp_extract_minutiae(FpImage *img, GAsyncResult *res, void *user_data)
{
    GPtrArray *minutiaes    = NULL;
    g_autoptr(GError) error = NULL;
    tAUTOMATON_DATA *aut    = (tAUTOMATON_DATA *) user_data;

    if (fp_image_detect_minutiae_finish(img,res,&error))
    {
        minutiaes = fp_image_get_minutiae(img);
        if (minutiaes != NULL)
        {
            gint img_w = fp_image_get_width(img);
            gint img_h = fp_image_get_height(img);
            // Do something

        }
        else
            LogError("Error retrieving minutiae");
    }
    else
    {
        LogError("Error retrieving minutiae from FingerPrint. %s",(error) ? error->message : "Unknown Error");
        if (error != NULL && error->code == G_IO_ERROR_CANCELLED)
            g_cancellable_reset(aut->ctx.clops);
    }

    KernelInsertEvent(aut->fsm->aut_id,AUT_EVT_DATA,NULL,0);
}

//---------------------------------------------------------------------------

static void etr_fp_dev_capture_cb(FpDevice *dev, GAsyncResult *res, void *user_data)
{
    int result;
    FpImage *image = NULL;
    g_autoptr(GError) error = NULL;
    tAUTOMATON_DATA *aut = (tAUTOMATON_DATA *) user_data;

    image = fp_device_capture_finish(dev, res, &error);

    if (!image)
    {
        LogError("Error capturing fingerprint: %s",error->message);

        if (aut->ctx.cap_cb)
            aut->ctx.cap_cb(error->code,NULL,aut->ctx.u_data);

        if (error->code == G_IO_ERROR_CANCELLED) {
            g_cancellable_reset(aut->ctx.clops);
            KernelInsertEvent(aut->fsm->aut_id,AUT_EVT_DATA,NULL,0);
        }

        else {

            etr_fp_dev_close(aut);
            KernelInsertEvent(aut->fsm->aut_id,AUT_EVT_REMOVED,NULL,0);
        }

        return;
    }

    if (aut->ctx.imgpath != NULL)
        if ((result = etr_fp_save_image_to_pgm(image, aut->ctx.imgpath)) < 0)
            LogError("Unable to save the image in specified path: %s. Error code: %d",aut->ctx.imgpath,result);

    fp_image_detect_minutiae(image,aut->ctx.clops,(GAsyncReadyCallback)etr_fp_extract_minutiae,aut);
}
//---------------------------------------------------------------------------

gboolean etr_fp_start_capture(gpointer data)
{
    tAUTOMATON_DATA *aut = (tAUTOMATON_DATA *) data;

    fp_device_capture(aut->ctx.device, TRUE, aut->ctx.clops, (GAsyncReadyCallback) etr_fp_dev_capture_cb, aut);

    return FALSE;
}
//---------------------------------------------------------------------------

void capturing__entry(void* aut_data)
{
    g_idle_add(etr_fp_start_capture,aut_data);
}
//---------------------------------------------------------------------------

static gboolean etr_fp_dev_close(gpointer data)
{
    g_autoptr(GError) gerror = NULL;
    tAUTOMATON_DATA *aut = (tAUTOMATON_DATA *)data;

    if (!fp_device_close_sync(aut->ctx.device,NULL,&gerror))
        LogError("Error closing device: %s",gerror->message);

    g_main_loop_quit(aut->ctx.gmloop);

    return FALSE;
}
//---------------------------------------------------------------------------

int etr_fp_init(void *aut)
{
    /*
      do other things.
    */

    if (pthread_create(&aut->ctx.event_t,NULL,&etr_fp_gmain_loop,aut))
    {
        LogError("%s:Id%d Unable to create glib event loop thread",K_ETR_FP_API_PREFIX,id);
        return K_ETR_FP_FAILURE;
    }

    return K_ETR_FP_OK;
}
//---------------------------------------------------------------------------

int etr_fp_end(void *aut)
{
    // Free libfrpint, glib resources when gmainloop ends free automaton.;
    g_idle_add_full(G_PRIORITY_HIGH_IDLE,etr_fp_dev_close,aut,NULL);
    pthread_join(aut->ctx.event_t,NULL);

    return 0;
}
//---------------------------------------------------------------------------



I have read some things about valgrind with Glib and possible problems. So, my first question is:

Can I use Valgrind with libfprint?

When I run valgrind with the following configuration:

valgrind --leak-check=full --show-leak-kinds=definite,indirect --track-origins=yes --verbose --log-file=valgrind-out.txt ./myapp

The following catches my attention:

==35461== 1,113,600 bytes in 10 blocks are indirectly lost in loss record 910 of 912
==35461==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==35461==    by 0x4AECCB8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x5450990: binarize_image_V2 (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x5450B3C: binarize_V2 (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x544605A: lfs_detect_minutiae_V2 (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x543EE8D: get_minutiae (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x540E7C1: fp_image_detect_minutiae_thread_func (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x8457C81: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.6)
==35461==    by 0x4B111B3: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x4B10910: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x858C608: start_thread (pthread_create.c:477)
==35461==    by 0x4CE2292: clone (clone.S:95)
==35461==
==35461== 1,113,600 bytes in 10 blocks are indirectly lost in loss record 911 of 912
==35461==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==35461==    by 0x4AECCB8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x540EF98: fp_image_detect_minutiae (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x484E10B: etr_fp_dev_capture_cb (fingerprint.c:528)
==35461==    by 0x8456F68: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.6)
==35461==    by 0x8457B5C: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.6)
==35461==    by 0x54375AA: fp_device_task_return_in_idle_cb (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x4AE6E6D: g_main_context_dispatch (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x4AE721F: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x4AE7512: g_main_loop_run (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x484DAA7: etr_fp_gmain_loop (fingerprint.c:401)
==35461==    by 0x858C608: start_thread (pthread_create.c:477)
==35461==
==35461== 2,333,120 (800 direct, 2,332,320 indirect) bytes in 10 blocks are definitely lost in loss record 912 of 912
==35461==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==35461==    by 0x4AECCB8: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x4B052A5: g_slice_alloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x4B058CD: g_slice_alloc0 (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.6400.6)
==35461==    by 0x837B0CF: g_type_create_instance (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.6)
==35461==    by 0x835A34C: ??? (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.6)
==35461==    by 0x835C377: g_object_new_valist (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.6)
==35461==    by 0x835C6CC: g_object_new (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.6400.6)
==35461==    by 0x5428644: imaging_run_state (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x543E345: transfer_finish_cb (in /usr/lib/x86_64-linux-gnu/libfprint.so.2.0.0)
==35461==    by 0x8456F68: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.6)
==35461==    by 0x8456FAC: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.6400.6)
==35461==
==35461== LEAK SUMMARY:
==35461==    definitely lost: 1,128 bytes in 22 blocks
==35461==    indirectly lost: 2,334,793 bytes in 2,604 blocks
==35461==      possibly lost: 34,119 bytes in 142 blocks
==35461==    still reachable: 190,826 bytes in 1,292 blocks
==35461==                       of which reachable via heuristic:
==35461==                         length64           : 1,160 bytes in 29 blocks
==35461==                         newarray           : 1,584 bytes in 19 blocks
==35461==         suppressed: 0 bytes in 0 blocks
==35461== Reachable blocks (those to which a pointer was found) are not shown.
==35461== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==35461==
==35461== ERROR SUMMARY: 135 errors from 135 contexts (suppressed: 0 from 0)

So fp_image_detect_minutiae have a memory leak?

Or maybe is a Valgrind problem. Every time I run a capture the memory usage grows and it doesn't seem to return the resources used.
I am executing the g_main_loop_run in another thread and the calls to the capture function are made using g_idle_add

Another problem detected is when unplug device, next call capture process. The removed device error is detected correctly but when I reinitialize the library creating a new object of type:


  *   FPContext
  *   GmainLoop

Have the next error:

(process:35): libfprint-context-DEBUG: 17:47:21.078: No driver found for USB device 1D6B:0001  ---> Device was removed and not plugged in yet .
(process:35): libfprint-image_device-DEBUG: 17:47:21.225: Image device open completed --> Device plugged in again, free up memory and create new objects.
(process:35): libfprint-device-DEBUG: 17:47:21.225: Device reported open completion
(process:35): libfprint-device-DEBUG: 17:47:21.225: Completing action FPI_DEVICE_ACTION_OPEN in idle!
(process:35): GLib-CRITICAL **: 17:47:21.226: g_ptr_array_find_with_equal_func: assertion 'haystack != NULL' failed
(process:35): libfprint-context-CRITICAL **: 17:47:21.226: remove_device_idle_cb: assertion 'g_ptr_array_find (priv->devices, data->device, &idx)' failed


The library works fine when the device is reconnected, but I want to know about these 2 errors.
Thanks for all the support provided.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/fprint/attachments/20210420/e9f41a6e/attachment-0001.htm>


More information about the fprint mailing list