Code

patches: Added bts770690_java_jni_thread_detach.
authorSebastian Harl <sh@tokkee.org>
Sun, 23 Nov 2014 13:15:04 +0000 (14:15 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 23 Nov 2014 13:15:04 +0000 (14:15 +0100)
Upstream fix for locking up the Java plugin by not properly detaching from the
JVM in error conditions. Thanks to Marc Fournier for reporting this.

Closes: #770690
debian/changelog
debian/patches/00list
debian/patches/bts770690_java_jni_thread_detach.dpatch [new file with mode: 0755]

index 12045897af05d0b816c15ebe57ced28dd88713fc..950af5118f33e70261062c57132ad7ec0295b8b5 100644 (file)
@@ -16,6 +16,9 @@ collectd (5.4.1-6) UNRELEASED; urgency=medium
     - Added bts770688_snmp_memleak: upstream fix for a memory leak in the
       SNMP plugin; thanks to Marc Fournier for reporting this
       (Closes: #770688).
+    - Added bts770690_java_jni_thread_detach: upstream fix for locking up the
+      Java plugin by not properly detaching from the JVM in error conditions;
+      thanks to Marc Fournier for reporting this (Closes: #770690).
 
  -- Sebastian Harl <tokkee@debian.org>  Sun, 23 Nov 2014 13:04:03 +0100
 
index 51d49a0ec626c772a02d2a1243ffe5b56d5fb9f6..92316ee5157aa87bf8352773c909f7388ff893de 100644 (file)
@@ -9,3 +9,4 @@ bts747093_lvm_segfault.dpatch
 bts770683_curl_init.dpatch
 bts750440_config_segfault.dpatch
 bts770688_snmp_memleak.dpatch
+bts770690_java_jni_thread_detach.dpatch
diff --git a/debian/patches/bts770690_java_jni_thread_detach.dpatch b/debian/patches/bts770690_java_jni_thread_detach.dpatch
new file mode 100755 (executable)
index 0000000..67a9c77
--- /dev/null
@@ -0,0 +1,205 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## bts770690_java_jni_thread_detach.dpatch by Florian Forster <octo@google.com>
+##
+## DP: java plugin: Make sure cjni_thread_detach() is called on all paths.
+## DP: Each call to cjni_thread_attach() much be accompanied by a call to
+## DP: cjni_thread_detach(). Some error handling cases were missing the call,
+## DP: potentially locking the plugin up.
+## DP:
+## DP: Also ensure that cjni_thread_detach() does not hide the status of other
+## DP: operations.
+## DP:
+## DP: Upstream commit:
+## DP: https://github.com/collectd/collectd/commit/513a5ca
+
+@DPATCH@
+
+diff a/src/java.c b/src/java.c
+--- a/src/java.c
++++ b/src/java.c
+@@ -2115,7 +2115,7 @@ static int cjni_thread_detach (void) /* {{{ */
+   cjni_env->jvm_env = NULL;
+   return (0);
+-} /* }}} JNIEnv *cjni_thread_attach */
++} /* }}} int cjni_thread_detach */
+ static int cjni_config_add_jvm_arg (oconfig_item_t *ci) /* {{{ */
+ {
+@@ -2468,7 +2468,6 @@ static int cjni_read (user_data_t *ud) /* {{{ */
+ {
+   JNIEnv *jvm_env;
+   cjni_callback_info_t *cbi;
+-  int status;
+   int ret_status;
+   if (jvm == NULL)
+@@ -2492,13 +2491,7 @@ static int cjni_read (user_data_t *ud) /* {{{ */
+   ret_status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object,
+       cbi->method);
+-  status = cjni_thread_detach ();
+-  if (status != 0)
+-  {
+-    ERROR ("java plugin: cjni_read: cjni_thread_detach failed.");
+-    return (-1);
+-  }
+-
++  cjni_thread_detach ();
+   return (ret_status);
+ } /* }}} int cjni_read */
+@@ -2509,7 +2502,6 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+   JNIEnv *jvm_env;
+   cjni_callback_info_t *cbi;
+   jobject vl_java;
+-  int status;
+   int ret_status;
+   if (jvm == NULL)
+@@ -2534,6 +2526,7 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+   if (vl_java == NULL)
+   {
+     ERROR ("java plugin: cjni_write: ctoj_value_list failed.");
++    cjni_thread_detach ();
+     return (-1);
+   }
+@@ -2542,13 +2535,7 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+   (*jvm_env)->DeleteLocalRef (jvm_env, vl_java);
+-  status = cjni_thread_detach ();
+-  if (status != 0)
+-  {
+-    ERROR ("java plugin: cjni_write: cjni_thread_detach failed.");
+-    return (-1);
+-  }
+-
++  cjni_thread_detach ();
+   return (ret_status);
+ } /* }}} int cjni_write */
+@@ -2560,7 +2547,6 @@ static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */
+   cjni_callback_info_t *cbi;
+   jobject o_timeout;
+   jobject o_identifier;
+-  int status;
+   int ret_status;
+   if (jvm == NULL)
+@@ -2587,6 +2573,7 @@ static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */
+   {
+     ERROR ("java plugin: cjni_flush: Converting double "
+         "to Number object failed.");
++    cjni_thread_detach ();
+     return (-1);
+   }
+@@ -2598,6 +2585,7 @@ static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */
+     {
+       (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout);
+       ERROR ("java plugin: cjni_flush: NewStringUTF failed.");
++      cjni_thread_detach ();
+       return (-1);
+     }
+   }
+@@ -2608,13 +2596,7 @@ static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */
+   (*jvm_env)->DeleteLocalRef (jvm_env, o_identifier);
+   (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout);
+-  status = cjni_thread_detach ();
+-  if (status != 0)
+-  {
+-    ERROR ("java plugin: cjni_flush: cjni_thread_detach failed.");
+-    return (-1);
+-  }
+-
++  cjni_thread_detach ();
+   return (ret_status);
+ } /* }}} int cjni_flush */
+@@ -2640,7 +2622,10 @@ static void cjni_log (int severity, const char *message, /* {{{ */
+   o_message = (*jvm_env)->NewStringUTF (jvm_env, message);
+   if (o_message == NULL)
++  {
++    cjni_thread_detach ();
+     return;
++  }
+   (*jvm_env)->CallVoidMethod (jvm_env,
+       cbi->object, cbi->method, (jint) severity, o_message);
+@@ -2658,7 +2643,6 @@ static int cjni_notification (const notification_t *n, /* {{{ */
+   JNIEnv *jvm_env;
+   cjni_callback_info_t *cbi;
+   jobject o_notification;
+-  int status;
+   int ret_status;
+   if (jvm == NULL)
+@@ -2683,6 +2667,7 @@ static int cjni_notification (const notification_t *n, /* {{{ */
+   if (o_notification == NULL)
+   {
+     ERROR ("java plugin: cjni_notification: ctoj_notification failed.");
++    cjni_thread_detach ();
+     return (-1);
+   }
+@@ -2691,13 +2676,7 @@ static int cjni_notification (const notification_t *n, /* {{{ */
+   (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
+-  status = cjni_thread_detach ();
+-  if (status != 0)
+-  {
+-    ERROR ("java plugin: cjni_read: cjni_thread_detach failed.");
+-    return (-1);
+-  }
+-
++  cjni_thread_detach ();
+   return (ret_status);
+ } /* }}} int cjni_notification */
+@@ -2725,24 +2704,20 @@ static int cjni_match_target_create (const oconfig_item_t *ci, /* {{{ */
+       (*jvm_env)->DeleteLocalRef (jvm_env, cbi_ret->object); \
+   } \
+   free (cbi_ret); \
+-  if (jvm_env != NULL) { \
+-    if (o_ci != NULL) \
+-      (*jvm_env)->DeleteLocalRef (jvm_env, o_ci); \
+-    cjni_thread_detach (); \
+-  } \
++  if (o_ci != NULL) \
++    (*jvm_env)->DeleteLocalRef (jvm_env, o_ci); \
++  cjni_thread_detach (); \
+   return (status)
+   if (jvm == NULL)
+   {
+     ERROR ("java plugin: cjni_read: jvm == NULL");
+-    BAIL_OUT (-1);
++    return (-1);
+   }
+   jvm_env = cjni_thread_attach ();
+   if (jvm_env == NULL)
+-  {
+-    BAIL_OUT (-1);
+-  }
++    return (-1);
+   /* Find out whether to create a match or a target. */
+   if (strcasecmp ("Match", ci->key) == 0)
+@@ -2936,10 +2911,7 @@ static int cjni_match_target_invoke (const data_set_t *ds, /* {{{ */
+     }
+   } /* if (cbi->type == CB_TYPE_TARGET) */
+-  status = cjni_thread_detach ();
+-  if (status != 0)
+-    ERROR ("java plugin: cjni_read: cjni_thread_detach failed.");
+-
++  cjni_thread_detach ();
+   return (ret_status);
+ } /* }}} int cjni_match_target_invoke */