Next Previous Contents

19. Callback Data Database

Squid's extensive use of callback functions makes it very susceptible to memory access errors. For a blocking operation with callback functions, the normal sequence of events is as follows:

        callback_data = malloc(...);
        ...
        fooOperationStart(bar, callback_func, callback_data);
        ...
        fooOperationComplete(...);
        callback_func(callback_data, ....);
        ...
        free(callback_data);
However, things become more interesting if we want or need to free the callback_data, or otherwise cancel the callback, before the operation completes.

The callback data database lets us do this in a uniform and safe manner. Every callback_data pointer must be added to the database. It is then locked while the blocking operation executes elsewhere, and is freed when the operation completes. The normal sequence of events is:

        callback_data = malloc(...);
        cbdataAdd(callback_data);
        ...
        cbdataLock(callback_data);
        fooOperationStart(bar, callback_func, callback_data);
        ...
        fooOperationComplete(...);
        if (cbdataValid(callback_data)) {
                callback_func(callback_data, ....);
        cbdataUnlock(callback_data);
        cbdataFree(callback_data);

With this scheme, nothing bad happens if cbdataFree gets called before cbdataUnlock:

        callback_data = malloc(...);
        cbdataAdd(callback_data);
        ...
        cbdataLock(callback_data);
        fooOperationStart(bar, callback_func, callback_data);
        ...
        cbdataFree(callback_data);
        ...
        fooOperationComplete(...);
        if (cbdataValid(callback_data)) {
                callback_func(callback_data, ....);
        cbdataUnlock(callback_data);
In this case, when cbdataFree is called before cbdataUnlock, the callback_data gets marked as invalid. Before executing the callback function, cbdataValid will return 0 and callback_func is never executed. When cbdataUnlock gets called, it notices that the callback_data is invalid and will then call cbdataFree.


Next Previous Contents