On 2/15/23 17:23, Richard W.M. Jones wrote:
> On Wed, Feb 15, 2023 at 03:11:34PM +0100, Laszlo Ersek wrote:
>> The "name##_iter" function is used 11 times in libnbd; in all those cases,
>> "name" is "string_vector", and the "f" callback is "free":
>>
>>   string_vector_iter (..., (void *) free);
>>
>> Casting "free" to (void*) is ugly. (Well-defined by POSIX, but still.)
>>
>> Furthermore, in all 11 cases, the freeing of the vector's strings is
>> immediately followed by the release of the vector's array-of-pointers too.
>> (This additional step is not expressed consistently across libnbd: it's
>> sometimes spelled as free(vec.ptr), sometimes as
>> string_vector_reset(&vec).)
>>
>> Remove the generic "name##_iter" function definition, and introduce
>> "name##_empty", which performs both steps at the same time. Convert the
>> call sites. (Note that the converted code performs more cleanup steps in
>> some cases than strictly necessary, but the extra work is harmless, and
>> arguably beneficial for clarity / consistency.)
>>
>> Expose the "name##_empty" function definition with a new, separate macro:
>> DEFINE_VECTOR_EMPTY(). The existent DEFINE_VECTOR_TYPE() macro permits
>> such element types that are not pointers, or are pointers to const- and/or
>> volatile-qualified objects. Whereas "name##_empty" requires that the
>> elements be pointers to dynamically allocated, non-const, non-volatile
>> objects.
>>
>> Signed-off-by: Laszlo Ersek <ler...@redhat.com>
>> ---
>>  common/utils/string-vector.h                 |  1 +
>>  common/utils/vector.h                        | 27 +++++++++++++-------
>>  generator/states-connect-socket-activation.c |  9 +++----
>>  lib/handle.c                                 | 12 +++------
>>  lib/utils.c                                  |  6 ++---
>>  common/utils/test-vector.c                   |  3 +--
>>  info/show.c                                  |  3 +--
>>  7 files changed, 30 insertions(+), 31 deletions(-)
>>
>> diff --git a/common/utils/string-vector.h b/common/utils/string-vector.h
>> index aa33fd48ceb5..78d0b4f9bf10 100644
>> --- a/common/utils/string-vector.h
>> +++ b/common/utils/string-vector.h
>> @@ -38,5 +38,6 @@
>>  #include "vector.h"
>>  
>>  DEFINE_VECTOR_TYPE (string_vector, char *);
>> +DEFINE_VECTOR_EMPTY (string_vector);
>>  
>>  #endif /* STRING_VECTOR_H */
>> diff --git a/common/utils/vector.h b/common/utils/vector.h
>> index fb2482c853ff..14bf5b0ddbc0 100644
>> --- a/common/utils/vector.h
>> +++ b/common/utils/vector.h
>> @@ -150,15 +150,6 @@
>>      v->len = v->cap = 0;                                                \
>>    }                                                                     \
>>                                                                          \
>> -  /* Iterate over the vector, calling f() on each element. */           \
>> -  static inline void __attribute__ ((__unused__))                       \
>> -  name##_iter (name *v, void (*f) (type elem))                          \
>> -  {                                                                     \
>> -    size_t i;                                                           \
>> -    for (i = 0; i < v->len; ++i)                                        \
>> -      f (v->ptr[i]);                                                    \
>> -  }                                                                     \
>> -                                                                        \
> 
> What's the reason for removing iter?  It's used by nbdkit in ways that
> don't involve free().  I'd prefer if we leave this definition in.

Good point -- the header is shared by nbdkit and libnbd, but (because
the latter are two separate projects) any single git-grep will cover
only one.

I'll restore _iter.

> 
>>    /* Sort the elements of the vector. */                                \
>>    static inline void __attribute__ ((__unused__))                       \
>>    name##_sort (name *v,                                                 \
>> @@ -180,6 +171,24 @@
>>  
>>  #define empty_vector { .ptr = NULL, .len = 0, .cap = 0 }
>>  
>> +/* This macro should only be used if:
>> + * - the vector contains pointers, and
>> + * - the pointed-to objects are:
>> + *   - neither const- nor volatile-qualified, and
>> + *   - allocated with malloc() or equivalent.
>> + */
>> +#define DEFINE_VECTOR_EMPTY(name)                                      \
> 
> I'm going to be that guy ...

Yes, someone has to be! I knew it was virtually impossible for me to get
the name right at the first try :)

> 
> Can we call it ADD_VECTOR_EMPTY_METHOD or similar/better?

Eric, any comments?

> Otherwise it seems like DEFINE_VECTOR_EMPTY is an alternative to
> DEFINE_VECTOR_TYPE (which I thought was the case initially), rather
> than something you have to call in addition to DEFINE_VECTOR_TYPE.
> 
> The rest seems fine.

Thanks!
Laszlo

> 
> Rich.
> 
>> +  /* Call free() on each element of the vector, then reset the vector. \
>> +   */                                                                  \
>> +  static inline void __attribute__ ((__unused__))                      \
>> +  name##_empty (name *v)                                               \
>> +  {                                                                    \
>> +    size_t i;                                                          \
>> +    for (i = 0; i < v->len; ++i)                                       \
>> +      free (v->ptr[i]);                                                \
>> +    name##_reset (v);                                                  \
>> +  }
>> +
>>  struct generic_vector {
>>    void *ptr;
>>    size_t len;
>> diff --git a/generator/states-connect-socket-activation.c 
>> b/generator/states-connect-socket-activation.c
>> index 7138e7638e30..3b621b8be44f 100644
>> --- a/generator/states-connect-socket-activation.c
>> +++ b/generator/states-connect-socket-activation.c
>> @@ -91,8 +91,7 @@ prepare_socket_activation_environment (string_vector *env)
>>  
>>   err:
>>    set_error (errno, "malloc");
>> -  string_vector_iter (env, (void *) free);
>> -  free (env->ptr);
>> +  string_vector_empty (env);
>>    return -1;
>>  }
>>  
>> @@ -166,8 +165,7 @@  CONNECT_SA.START:
>>      SET_NEXT_STATE (%.DEAD);
>>      set_error (errno, "fork");
>>      close (s);
>> -    string_vector_iter (&env, (void *) free);
>> -    free (env.ptr);
>> +    string_vector_empty (&env);
>>      return 0;
>>    }
>>    if (pid == 0) {         /* child - run command */
>> @@ -210,8 +208,7 @@  CONNECT_SA.START:
>>  
>>    /* Parent. */
>>    close (s);
>> -  string_vector_iter (&env, (void *) free);
>> -  free (env.ptr);
>> +  string_vector_empty (&env);
>>    h->pid = pid;
>>  
>>    h->connaddrlen = sizeof addr;
>> diff --git a/lib/handle.c b/lib/handle.c
>> index dfd8c2e5cdb9..fb92f16e6c91 100644
>> --- a/lib/handle.c
>> +++ b/lib/handle.c
>> @@ -128,8 +128,7 @@ nbd_close (struct nbd_handle *h)
>>    /* Free user callbacks first. */
>>    nbd_unlocked_clear_debug_callback (h);
>>  
>> -  string_vector_iter (&h->querylist, (void *) free);
>> -  free (h->querylist.ptr);
>> +  string_vector_empty (&h->querylist);
>>    free (h->bs_entries);
>>    nbd_internal_reset_size_and_flags (h);
>>    for (i = 0; i < h->meta_contexts.len; ++i)
>> @@ -139,8 +138,7 @@ nbd_close (struct nbd_handle *h)
>>    free_cmd_list (h->cmds_to_issue);
>>    free_cmd_list (h->cmds_in_flight);
>>    free_cmd_list (h->cmds_done);
>> -  string_vector_iter (&h->argv, (void *) free);
>> -  free (h->argv.ptr);
>> +  string_vector_empty (&h->argv);
>>    if (h->sact_sockpath) {
>>      if (h->pid > 0)
>>        kill (h->pid, SIGTERM);
>> @@ -164,8 +162,7 @@ nbd_close (struct nbd_handle *h)
>>    free (h->tls_certificates);
>>    free (h->tls_username);
>>    free (h->tls_psk_file);
>> -  string_vector_iter (&h->request_meta_contexts, (void *) free);
>> -  free (h->request_meta_contexts.ptr);
>> +  string_vector_empty (&h->request_meta_contexts);
>>    free (h->hname);
>>    pthread_mutex_destroy (&h->lock);
>>    free (h);
>> @@ -379,8 +376,7 @@ nbd_unlocked_get_meta_context (struct nbd_handle *h, 
>> size_t i)
>>  int
>>  nbd_unlocked_clear_meta_contexts (struct nbd_handle *h)
>>  {
>> -  string_vector_iter (&h->request_meta_contexts, (void *) free);
>> -  string_vector_reset (&h->request_meta_contexts);
>> +  string_vector_empty (&h->request_meta_contexts);
>>    return 0;
>>  }
>>  
>> diff --git a/lib/utils.c b/lib/utils.c
>> index c229ebfc6106..bba4b3846e77 100644
>> --- a/lib/utils.c
>> +++ b/lib/utils.c
>> @@ -93,8 +93,7 @@ nbd_internal_set_argv (struct nbd_handle *h, char **argv)
>>      return -1;
>>    }
>>  
>> -  string_vector_iter (&h->argv, (void *) free);
>> -  string_vector_reset (&h->argv);
>> +  string_vector_empty (&h->argv);
>>  
>>    if (nbd_internal_copy_string_list (&h->argv, argv) == -1) {
>>      set_error (errno, "realloc");
>> @@ -110,8 +109,7 @@ nbd_internal_set_argv (struct nbd_handle *h, char **argv)
>>  int
>>  nbd_internal_set_querylist (struct nbd_handle *h, char **queries)
>>  {
>> -  string_vector_iter (&h->querylist, (void *) free);
>> -  string_vector_reset (&h->querylist);
>> +  string_vector_empty (&h->querylist);
>>  
>>    if (queries) {
>>      if (nbd_internal_copy_string_list (&h->querylist, queries) == -1) {
>> diff --git a/common/utils/test-vector.c b/common/utils/test-vector.c
>> index 55c8ebeb8a1e..05ac5cec3dba 100644
>> --- a/common/utils/test-vector.c
>> +++ b/common/utils/test-vector.c
>> @@ -151,8 +151,7 @@ test_string_vector (void)
>>      printf ("%s\n", v.ptr[i]);
>>    assert (i == 10);
>>  
>> -  string_vector_iter (&v, (void*)free);
>> -  string_vector_reset (&v);
>> +  string_vector_empty (&v);
>>  }
>>  
>>  static void
>> diff --git a/info/show.c b/info/show.c
>> index 4bf596715cf9..e6c9b9bf1243 100644
>> --- a/info/show.c
>> +++ b/info/show.c
>> @@ -275,8 +275,7 @@ show_one_export (struct nbd_handle *nbd, const char 
>> *desc,
>>        fprintf (fp, "\t},\n");
>>    }
>>  
>> -  string_vector_iter (&contexts, (void *) free);
>> -  free (contexts.ptr);
>> +  string_vector_empty (&contexts);
>>    free (content);
>>    free (export_name);
>>    free (export_desc);
>>
>> _______________________________________________
>> Libguestfs mailing list
>> Libguestfs@redhat.com
>> https://listman.redhat.com/mailman/listinfo/libguestfs
> 

_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to