Blame SOURCES/Use-pthread-keys-for-thread-local-storage.patch

cc8bf3
From 17dbcfaff5e7d917eb48579dc8e5f60c95a30981 Mon Sep 17 00:00:00 2001
cc8bf3
From: Simo Sorce <simo@redhat.com>
cc8bf3
Date: Thu, 20 Sep 2018 17:37:53 -0400
cc8bf3
Subject: [PATCH] Use pthread keys for thread local storage
cc8bf3
cc8bf3
This interface is slower but also more portable, and more importantly
cc8bf3
it provides a way to specify destructor that is called when a thread
cc8bf3
is canceled so we stop leaking memory.
cc8bf3
cc8bf3
Signed-off-by: Simo Sorce <simo@redhat.com>
cc8bf3
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
cc8bf3
Merges: #233
cc8bf3
(cherry picked from commit 0faccc1441bc7a6b3e8bd806f22c8a961e5f586e)
cc8bf3
(cherry picked from commit 89dc0ee157caa4617d32fd72287849296d7fe26d)
cc8bf3
---
cc8bf3
 proxy/src/client/gpm_common.c         |  2 +
cc8bf3
 proxy/src/client/gpm_display_status.c | 57 ++++++++++++++++++---------
cc8bf3
 proxy/src/client/gssapi_gpm.h         |  1 +
cc8bf3
 3 files changed, 42 insertions(+), 18 deletions(-)
cc8bf3
cc8bf3
diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c
cc8bf3
index 0d314fa..b482efb 100644
cc8bf3
--- a/proxy/src/client/gpm_common.c
cc8bf3
+++ b/proxy/src/client/gpm_common.c
cc8bf3
@@ -55,6 +55,8 @@ static void gpm_init_once(void)
cc8bf3
     gpm_global_ctx.next_xid = rand_r(&seedp);
cc8bf3
 
cc8bf3
     pthread_mutexattr_destroy(&attr);
cc8bf3
+
cc8bf3
+    gpm_display_status_init_once();
cc8bf3
 }
cc8bf3
 
cc8bf3
 static int get_pipe_name(char *name)
cc8bf3
diff --git a/proxy/src/client/gpm_display_status.c b/proxy/src/client/gpm_display_status.c
cc8bf3
index bbb546f..e3aa4ea 100644
cc8bf3
--- a/proxy/src/client/gpm_display_status.c
cc8bf3
+++ b/proxy/src/client/gpm_display_status.c
cc8bf3
@@ -1,27 +1,47 @@
cc8bf3
 /* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */
cc8bf3
 
cc8bf3
 #include "gssapi_gpm.h"
cc8bf3
+#include <pthread.h>
cc8bf3
 
cc8bf3
-__thread gssx_status *tls_last_status = NULL;
cc8bf3
+static pthread_key_t gpm_last_status;
cc8bf3
 
cc8bf3
-/* Thread local storage for return status.
cc8bf3
- * FIXME: it's not the most portable construct, so may need fixing in future */
cc8bf3
+static void gpm_destroy_last_status(void *arg)
cc8bf3
+{
cc8bf3
+    gssx_status *status = (gssx_status *)arg;
cc8bf3
+    xdr_free((xdrproc_t)xdr_gssx_status, (char *)status);
cc8bf3
+    free(status);
cc8bf3
+}
cc8bf3
+
cc8bf3
+void gpm_display_status_init_once(void)
cc8bf3
+{
cc8bf3
+    (void)pthread_key_create(&gpm_last_status, gpm_destroy_last_status);
cc8bf3
+}
cc8bf3
+
cc8bf3
+/* Portable thread local storage for return status. */
cc8bf3
 void gpm_save_status(gssx_status *status)
cc8bf3
 {
cc8bf3
+    gssx_status *last_status;
cc8bf3
     int ret;
cc8bf3
 
cc8bf3
-    if (tls_last_status) {
cc8bf3
-        xdr_free((xdrproc_t)xdr_gssx_status, (char *)tls_last_status);
cc8bf3
-        free(tls_last_status);
cc8bf3
+    last_status = (gssx_status *)pthread_getspecific(gpm_last_status);
cc8bf3
+    if (last_status != NULL) {
cc8bf3
+        /* store NULL first so we do not risk a double free if we are
cc8bf3
+         * racing on a pthread_cancel */
cc8bf3
+        pthread_setspecific(gpm_last_status, NULL);
cc8bf3
+        gpm_destroy_last_status(last_status);
cc8bf3
     }
cc8bf3
 
cc8bf3
-    ret = gp_copy_gssx_status_alloc(status, &tls_last_status);
cc8bf3
-    if (ret) {
cc8bf3
-        /* make sure tls_last_status is zeored on error */
cc8bf3
-        tls_last_status = NULL;
cc8bf3
+    ret = gp_copy_gssx_status_alloc(status, &last_status);
cc8bf3
+    if (ret == 0) {
cc8bf3
+        pthread_setspecific(gpm_last_status, last_status);
cc8bf3
     }
cc8bf3
 }
cc8bf3
 
cc8bf3
+gssx_status *gpm_get_saved_status(void)
cc8bf3
+{
cc8bf3
+    return (gssx_status *)pthread_getspecific(gpm_last_status);
cc8bf3
+}
cc8bf3
+
cc8bf3
 /* This funciton is used to record internal mech errors that are
cc8bf3
  * generated by the proxy client code */
cc8bf3
 void gpm_save_internal_status(uint32_t err, char *err_str)
cc8bf3
@@ -47,15 +67,16 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status,
cc8bf3
                              OM_uint32 *message_context,
cc8bf3
                              gss_buffer_t status_string)
cc8bf3
 {
cc8bf3
+    gssx_status *last_status = gpm_get_saved_status();
cc8bf3
     utf8string tmp;
cc8bf3
     int ret;
cc8bf3
 
cc8bf3
     switch(status_type) {
cc8bf3
     case GSS_C_GSS_CODE:
cc8bf3
-        if (tls_last_status &&
cc8bf3
-            tls_last_status->major_status == status_value &&
cc8bf3
-            tls_last_status->major_status_string.utf8string_len) {
cc8bf3
-                ret = gp_copy_utf8string(&tls_last_status->major_status_string,
cc8bf3
+        if (last_status &&
cc8bf3
+            last_status->major_status == status_value &&
cc8bf3
+            last_status->major_status_string.utf8string_len) {
cc8bf3
+                ret = gp_copy_utf8string(&last_status->major_status_string,
cc8bf3
                                          &tmp);
cc8bf3
                 if (ret) {
cc8bf3
                     *minor_status = ret;
cc8bf3
@@ -70,9 +91,9 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status,
cc8bf3
             return GSS_S_UNAVAILABLE;
cc8bf3
         }
cc8bf3
     case GSS_C_MECH_CODE:
cc8bf3
-        if (tls_last_status &&
cc8bf3
-            tls_last_status->minor_status == status_value &&
cc8bf3
-            tls_last_status->minor_status_string.utf8string_len) {
cc8bf3
+        if (last_status &&
cc8bf3
+            last_status->minor_status == status_value &&
cc8bf3
+            last_status->minor_status_string.utf8string_len) {
cc8bf3
 
cc8bf3
             if (*message_context) {
cc8bf3
                 /* we do not support multiple messages for now */
cc8bf3
@@ -80,7 +101,7 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status,
cc8bf3
                 return GSS_S_FAILURE;
cc8bf3
             }
cc8bf3
 
cc8bf3
-            ret = gp_copy_utf8string(&tls_last_status->minor_status_string,
cc8bf3
+            ret = gp_copy_utf8string(&last_status->minor_status_string,
cc8bf3
                                      &tmp);
cc8bf3
             if (ret) {
cc8bf3
                 *minor_status = ret;
cc8bf3
diff --git a/proxy/src/client/gssapi_gpm.h b/proxy/src/client/gssapi_gpm.h
cc8bf3
index 22beecf..61124e0 100644
cc8bf3
--- a/proxy/src/client/gssapi_gpm.h
cc8bf3
+++ b/proxy/src/client/gssapi_gpm.h
cc8bf3
@@ -23,6 +23,7 @@ OM_uint32 gpm_release_name(OM_uint32 *minor_status,
cc8bf3
 OM_uint32 gpm_release_buffer(OM_uint32 *minor_status,
cc8bf3
                              gss_buffer_t buffer);
cc8bf3
 
cc8bf3
+void gpm_display_status_init_once(void);
cc8bf3
 void gpm_save_status(gssx_status *status);
cc8bf3
 void gpm_save_internal_status(uint32_t err, char *err_str);
cc8bf3