Merged in master, thanks!

Jérémie

On Tue, Jun 05, 2018 at 12:11:20PM -0400, Michael Jeanson wrote:
> readdir_r() has been deprecated since glibc 2.24 [1].
> 
> We used readdir_r() in load_session_from_path() to be thread-safe
> since this function is part of liblttng-ust-ctl. However, according
> to readdir()'s man page, it's thread-safe as long as the directory
> stream it operates on is not shared across threads :
> 
>   In the current POSIX.1 specification (POSIX.1-2008), readdir(3) is
>   not required to be thread-safe. However, in modern
>   implementations (including the glibc implementation), concurrent
>   calls to readdir(3) that specify different directory streams are
>   thread-safe. Therefore, the use of readdir_r() is generally
>   unnecessary in multithreaded programs. In cases where multiple
>   threads must read from the same directory stream, using readdir(3)
>   with external synchronization is still preferable to the use of
>   readdir_r(), for the reasons given in the points above.
> 
> In our use-case where we open the directory stream in the same function,
> we know it won't be shared across threads and thus it's safe to use
> readdir(). Here is the relevevant bit from the POSIX.1 [2] spec :
> 
>   The returned pointer, and pointers within the structure, might be
>   invalidated or the structure or the storage areas might be overwritten
>   by a subsequent call to readdir() on the same directory stream. They shall
>   not be affected by a call to readdir() on a different directory stream.
> 
>  [1] https://sourceware.org/bugzilla/show_bug.cgi?id=19056
>  [2] http://pubs.opengroup.org/onlinepubs/9699919799/functions/readdir.html
> 
> Signed-off-by: Michael Jeanson <mjean...@efficios.com>
> ---
>  src/common/config/session-config.c | 54 ++++++++++++++----------------
>  1 file changed, 26 insertions(+), 28 deletions(-)
> 
> diff --git a/src/common/config/session-config.c 
> b/src/common/config/session-config.c
> index 624064a1..56db1195 100644
> --- a/src/common/config/session-config.c
> +++ b/src/common/config/session-config.c
> @@ -2953,23 +2953,6 @@ end:
>       return ret;
>  }
>  
> -/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
> -static
> -struct dirent *alloc_dirent(const char *path)
> -{
> -     size_t len;
> -     long name_max;
> -     struct dirent *entry;
> -
> -     name_max = pathconf(path, _PC_NAME_MAX);
> -     if (name_max == -1) {
> -             name_max = PATH_MAX;
> -     }
> -     len = offsetof(struct dirent, d_name) + name_max + 1;
> -     entry = zmalloc(len);
> -     return entry;
> -}
> -
>  static
>  int load_session_from_path(const char *path, const char *session_name,
>       struct session_config_validation_ctx *validation_ctx, int overwrite,
> @@ -3006,7 +2989,6 @@ int load_session_from_path(const char *path, const char 
> *session_name,
>               }
>       }
>       if (directory) {
> -             struct dirent *entry;
>               struct dirent *result;
>               size_t file_path_root_len;
>  
> @@ -3017,16 +2999,9 @@ int load_session_from_path(const char *path, const 
> char *session_name,
>                       goto end;
>               }
>  
> -             entry = alloc_dirent(path);
> -             if (!entry) {
> -                     ret = -LTTNG_ERR_NOMEM;
> -                     goto end;
> -             }
> -
>               ret = lttng_dynamic_buffer_append(&file_path, path, path_len);
>               if (ret) {
>                       ret = -LTTNG_ERR_NOMEM;
> -                     free(entry);
>                       goto end;
>               }
>  
> @@ -3040,8 +3015,32 @@ int load_session_from_path(const char *path, const 
> char *session_name,
>               file_path_root_len = file_path.size;
>  
>               /* Search for *.lttng files */
> -             while (!readdir_r(directory, entry, &result) && result) {
> -                     size_t file_name_len = strlen(result->d_name);
> +             for (;;) {
> +                     size_t file_name_len;
> +
> +                     /*
> +                      * When the end of the directory stream is reached, 
> NULL is
> +                      * returned and errno is kept unchanged. When an error 
> occurs,
> +                      * NULL is returned and errno is set accordingly. To
> +                      * distinguish between the two, set errno to zero before
> +                      * calling readdir().
> +                      *
> +                      * On success, readdir() returns a pointer to a dirent
> +                      * structure. (This structure may be statically 
> allocated, do
> +                      * not attempt to free(3) it.)
> +                      */
> +                     errno = 0;
> +                     result = readdir(directory);
> +
> +                     /* Reached end of dir stream or error out */
> +                     if (!result) {
> +                             if (errno) {
> +                                     PERROR("readdir");
> +                             }
> +                             break;
> +                     }
> +
> +                     file_name_len = strlen(result->d_name);
>  
>                       if (file_name_len <=
>                               sizeof(DEFAULT_SESSION_CONFIG_FILE_EXTENSION)) {
> @@ -3089,7 +3088,6 @@ int load_session_from_path(const char *path, const char 
> *session_name,
>                       }
>               }
>  
> -             free(entry);
>       } else {
>               ret = load_session_from_file(path, session_name,
>                       validation_ctx, overwrite, overrides);
> -- 
> 2.17.0
> 
_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to