#233 Use pthread keys for thread local storage
Merged 5 years ago by rharwood. Opened 5 years ago by simo.
simo/gssproxy tlsnoleak  into  master

file modified
+2
@@ -55,6 +55,8 @@ 

      gpm_global_ctx.next_xid = rand_r(&seedp);

  

      pthread_mutexattr_destroy(&attr);

+ 

+     gpm_display_status_init_once();

  }

  

  static int get_pipe_name(char *name)

file modified
+39 -18
@@ -1,27 +1,47 @@ 

  /* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */

  

  #include "gssapi_gpm.h"

+ #include <pthread.h>

  

- __thread gssx_status *tls_last_status = NULL;

+ static pthread_key_t gpm_last_status;

  

- /* Thread local storage for return status.

-  * FIXME: it's not the most portable construct, so may need fixing in future */

+ static void gpm_destroy_last_status(void *arg)

+ {

+     gssx_status *status = (gssx_status *)arg;

+     xdr_free((xdrproc_t)xdr_gssx_status, (char *)status);

+     free(status);

+ }

+ 

+ void gpm_display_status_init_once(void)

+ {

+     (void)pthread_key_create(&gpm_last_status, gpm_destroy_last_status);

+ }

+ 

+ /* Portable thread local storage for return status. */

  void gpm_save_status(gssx_status *status)

  {

+     gssx_status *last_status;

      int ret;

  

-     if (tls_last_status) {

-         xdr_free((xdrproc_t)xdr_gssx_status, (char *)tls_last_status);

-         free(tls_last_status);

+     last_status = (gssx_status *)pthread_getspecific(gpm_last_status);

+     if (last_status != NULL) {

+         /* store NULL first so we do not risk a double free if we are

+          * racing on a pthread_cancel */

+         pthread_setspecific(gpm_last_status, NULL);

+         gpm_destroy_last_status(last_status);

      }

  

-     ret = gp_copy_gssx_status_alloc(status, &tls_last_status);

-     if (ret) {

-         /* make sure tls_last_status is zeored on error */

-         tls_last_status = NULL;

+     ret = gp_copy_gssx_status_alloc(status, &last_status);

+     if (ret == 0) {

+         pthread_setspecific(gpm_last_status, last_status);

      }

  }

  

+ gssx_status *gpm_get_saved_status(void)

+ {

+     return (gssx_status *)pthread_getspecific(gpm_last_status);

+ }

+ 

  /* This funciton is used to record internal mech errors that are

   * generated by the proxy client code */

  void gpm_save_internal_status(uint32_t err, char *err_str)
@@ -47,15 +67,16 @@ 

                               OM_uint32 *message_context,

                               gss_buffer_t status_string)

  {

+     gssx_status *last_status = gpm_get_saved_status();

      utf8string tmp;

      int ret;

  

      switch(status_type) {

      case GSS_C_GSS_CODE:

-         if (tls_last_status &&

-             tls_last_status->major_status == status_value &&

-             tls_last_status->major_status_string.utf8string_len) {

-                 ret = gp_copy_utf8string(&tls_last_status->major_status_string,

+         if (last_status &&

+             last_status->major_status == status_value &&

+             last_status->major_status_string.utf8string_len) {

+                 ret = gp_copy_utf8string(&last_status->major_status_string,

                                           &tmp);

                  if (ret) {

                      *minor_status = ret;
@@ -70,9 +91,9 @@ 

              return GSS_S_UNAVAILABLE;

          }

      case GSS_C_MECH_CODE:

-         if (tls_last_status &&

-             tls_last_status->minor_status == status_value &&

-             tls_last_status->minor_status_string.utf8string_len) {

+         if (last_status &&

+             last_status->minor_status == status_value &&

+             last_status->minor_status_string.utf8string_len) {

  

              if (*message_context) {

                  /* we do not support multiple messages for now */
@@ -80,7 +101,7 @@ 

                  return GSS_S_FAILURE;

              }

  

-             ret = gp_copy_utf8string(&tls_last_status->minor_status_string,

+             ret = gp_copy_utf8string(&last_status->minor_status_string,

                                       &tmp);

              if (ret) {

                  *minor_status = ret;

file modified
+1
@@ -23,6 +23,7 @@ 

  OM_uint32 gpm_release_buffer(OM_uint32 *minor_status,

                               gss_buffer_t buffer);

  

+ void gpm_display_status_init_once(void);

  void gpm_save_status(gssx_status *status);

  void gpm_save_internal_status(uint32_t err, char *err_str);

  

This interface is slower but also more portable, and more importantly
it provides a way to specify destructor that is called when a thread
is canceled so we stop leaking memory.

Commit 0faccc1 fixes this pull-request

Pull-Request has been merged by rharwood

5 years ago