Can't seem to shutdown cef process

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Re: Can't seem to shutdown cef process

Postby aleitner » Tue Sep 19, 2023 5:52 pm

Code: Select all
typedef struct _shutdown_task {
    cef_task_t task;
    int ref_count;
} shutdown_task_t;
aleitner
Techie
 
Posts: 49
Joined: Fri Jun 16, 2023 12:05 pm

Re: Can't seem to shutdown cef process

Postby aleitner » Wed Sep 20, 2023 10:54 am

I've tried updating to use atomic_int but that didn't seem to help

Task Structure
Code: Select all
typedef struct _shutdown_task {
    cef_task_t task;
    atomic_int  ref_count;
} shutdown_task_t;


Add Ref callback
Code: Select all
static void CEF_CALLBACK add_ref_shutdown_task(struct _cef_base_ref_counted_t* base) {
    /**
     * The shutdown_task to be referenced. Convert from base structure to our wrap structure
     */
    shutdown_task_t* task = (shutdown_task_t*)base;

    if (task == NULL)
        return;

    fprintf(stderr, "add_ref_shutdown_task.\n");

    /* increment the reference count */
    atomic_fetch_add(&task->ref_count, 1);
}


Release Callback
Code: Select all
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
    shutdown_task_t* task = (shutdown_task_t*)base;

    fprintf(stderr, "release_shutdown_task.\n");

    if ( atomic_fetch_sub(&task->ref_count, 1) == 1) {
        free(task);
        task = NULL;
        return 1;
    }
   
    return 0;
}


has_one_ref Callback
Code: Select all
static int CEF_CALLBACK has_one_ref(struct _cef_base_ref_counted_t* base) {
    shutdown_task_t* task = (shutdown_task_t*)base;

    return task->ref_count == 1 ? 1 : 0;
}


execute Callback
Code: Select all
static void CEF_CALLBACK shutdown_execute(struct _cef_task_t* task) {
    fprintf(stderr, "shutdown.\n");
    cef_quit_message_loop();
}


Initialize task
Code: Select all
shutdown_task_t* create_shutdown_task() {
    shutdown_task_t* task = (shutdown_task_t*)calloc(1, sizeof(shutdown_task_t));

    task->task.base.size = sizeof(shutdown_task_t);
    task->task.base.add_ref = add_ref_shutdown_task;
    task->task.base.release = release_shutdown_task;
    task->task.base.has_one_ref = has_one_ref;
    task->task.execute = shutdown_execute;
    task->ref_count = 1;

    return task;
}


Post Task
Code: Select all
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);
aleitner
Techie
 
Posts: 49
Joined: Fri Jun 16, 2023 12:05 pm

Re: Can't seem to shutdown cef process

Postby magreenblatt » Wed Sep 20, 2023 11:28 am

I usually see
add_ref_shutdown_task.
release_shutdown_task.
free(): invalid pointer

This is strange, because the reference count in your code starts at 1. So I would expect the free() after 2 calls to release_shutdown_task.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Can't seem to shutdown cef process

Postby aleitner » Wed Sep 20, 2023 11:33 am

magreenblatt wrote:
I usually see
add_ref_shutdown_task.
release_shutdown_task.
free(): invalid pointer

This is strange, because the reference count in your code starts at 1. So I would expect the free() after 2 calls to release_shutdown_task.


I assume something is crashing before all the stderr prints.

Sometimes it does succeed and we see

add_ref_shutdown_task.
release_shutdown_task.
add_ref_shutdown_task.
release_shutdown_task.
shutdown.
release_shutdown_task.
aleitner
Techie
 
Posts: 49
Joined: Fri Jun 16, 2023 12:05 pm

Re: Can't seem to shutdown cef process

Postby magreenblatt » Wed Sep 20, 2023 11:51 am

aleitner wrote:Sometimes it does succeed and we see

add_ref_shutdown_task.
release_shutdown_task.
add_ref_shutdown_task.
release_shutdown_task.
shutdown.
release_shutdown_task.

That looks correct to me.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Can't seem to shutdown cef process

Postby ndesktop » Wed Sep 20, 2023 11:58 am

aleitner wrote:
Code: Select all
// release
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
    shutdown_task_t* task = (shutdown_task_t*)base;

    fprintf(stderr, "release_shutdown_task.\n");

    --task->ref_count;
   
    if (task->ref_count == 0) {
        if (task)
            free(task);       
        return 1;
    }
   
    return 0;
}



I'm not familiar with the C convention of addref/release in CEF (but I suppose is similar with what COM does), but shouldn't release return 0 when task->ref_count is 0 (and frees), and task->ref_count when it is > 0?
Something like this:
Code: Select all
static int CEF_CALLBACK release_shutdown_task(struct _cef_base_ref_counted_t* base) {
    shutdown_task_t* task = (shutdown_task_t*)base;
    int ref = --task->ref_count;
    if (ref == 0) {
        if (task)
            free(task);       
        return 0;
    }
    return ref;
}
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: Can't seem to shutdown cef process

Postby aleitner » Wed Sep 20, 2023 12:02 pm

https://github.com/chromiumembedded/cef ... capi.h#L61

Returns true (1) if the resulting reference count is 0.


And of course after I posted that it has yet to encounter any double free errors again. It all seems to be working. I am still curious on what the advantage of implementing reference counting is over just manually calling free()

With reference counting
Code: Select all
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);


vs
Without reference counting
Code: Select all
shutdown_task_t* task = create_shutdown_task();
cef_post_task(TID_UI, &task->task);
free(task);
aleitner
Techie
 
Posts: 49
Joined: Fri Jun 16, 2023 12:05 pm

Re: Can't seem to shutdown cef process

Postby ndesktop » Wed Sep 20, 2023 12:06 pm

Returns true (1) if the resulting reference count is 0.

Yes, I saw that after posting.
Maybe is something related to has_one_ref? I noticed you use atomic_ for addref and release, but a simple == 1 on has_one_ref.
Perhaps atomic_compare_exchange_strong ?
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: Can't seem to shutdown cef process

Postby magreenblatt » Wed Sep 20, 2023 12:19 pm

I am still curious on what the advantage of implementing reference counting is over just manually calling free()

If was the easiest way to manage object lifespan across multiple threads, delegates, etc. If we were to redesign the CEF API today (very unlikely) we might choose a more explicit form of lifespan management.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Previous

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 181 guests