Stefan Beller <sbel...@google.com> writes:

> This revamps the API of the attr subsystem to be thread safe.
> Before we had the question and its results in one struct type.
> The typical usage of the API was
>
>     static struct git_attr_check *check;
>
>     if (!check)
>         check = git_attr_check_initl("text", NULL);
>
>     git_check_attr(path, check);
>     act_on(check->value[0]);
>
> This has a couple of issues when it comes to thread safety:
>
> * the initialization is racy in this implementation. To make it
>   thread safe, we need to acquire a mutex, such that only one
>   thread is executing the code in git_attr_check_initl.
>   As we do not want to introduce a mutex at each call site,
>   this is best done in the attr code. However to do so, we need
>   to have access to the `check` variable, i.e. the API has to
>   look like
>     git_attr_check_initl(struct git_attr_check*, ...);

Make that a double-asterisk.  The same problem appears in an updated
example in technical/api-gitattributes.txt doc, but the example in
the commit log message (below) is correct.

> The usage of the new API will be:
>
>     /*
>      * The initl call will thread-safely check whether the
>      * struct git_attr_check has been initialized. We only
>      * want to do the initialization work once, hence we do
>      * that work inside a thread safe environment.
>      */
>     static struct git_attr_check *check;
>     git_attr_check_initl(&check, "text", NULL);
>
>     /*
>      * Obtain a pointer to a correctly sized result
>      * statically allocated on the stack; this macro:
>      */
>     GIT_ATTR_RESULT_INIT_FOR(myresult, 1);

Are you sure about this?  We've called attr_check_initl() already so
if this is declaring myresult, it would be decl-after-stmt.

>     /* Perform the check and act on it: */
>     git_check_attr(path, check, myresult);
>     act_on(myresult->value[0]);
>
>     /*
>      * No need to free the check as it is static, hence doesn't leak
>      * memory. The result is also static, so no need to free there either.
>      */

The latter half is questionable.  If it is "static" it wouldn't be
thread safe, no?  I think the diff in this patch for archive.c shows
that we only expect

        struct git_attr_result result[2];

upfront without RESULT_INIT_FOR(), and the reason why there is no
need to free the result[] is because it is on the stack.  And each
element in result[] may point at a string, but the string belongs to
the attr subsystem and must not be freed.

Reply via email to