[java-atk-wrapper] FIX SIGEV fatal error



commit 5bf850ab5acb43c4e961e4a44a49cf7e23d3f085
Author: Magdalen Berns <m berns thismagpie com>
Date:   Sat Jan 17 00:46:13 2015 +0000

    FIX SIGEV fatal error
    
    There was a SIGEV fatal error when running orca meaning
    the J2SE-access-bridge script was not identified. This
    was caused by some dodgy jni initialization and also a
    configuration bug in the keymaps. Resolving the issues
    allows the program to init but there is still some
    locking up in the g_cond(wait) to resolve.
    
    Bug: https://bugzilla.gnome.org/show_bug.cgi?id=742597

 jni/src/AtkWrapper.c                             |  180 ++++++++++++++--------
 jni/src/jawutil.c                                |   25 +++-
 wrapper/org/GNOME/Accessibility/AtkKeyEvent.java |    8 +-
 3 files changed, 138 insertions(+), 75 deletions(-)
---
diff --git a/jni/src/AtkWrapper.c b/jni/src/AtkWrapper.c
index dac74d8..ac45db9 100644
--- a/jni/src/AtkWrapper.c
+++ b/jni/src/AtkWrapper.c
@@ -21,7 +21,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <glib.h>
-#include <gmodule.h>
 #include <atk-bridge.h>
 #include <gdk/gdk.h>
 #include <X11/Xlib.h>
@@ -30,6 +29,13 @@
 #include "jawimpl.h"
 #include "jawtoplevel.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
 #define KEY_DISPATCH_NOT_DISPATCHED 0
 #define KEY_DISPATCH_CONSUMED 1
 #define KEY_DISPATCH_NOT_CONSUMED 2
@@ -40,6 +46,7 @@
 #define GDK_META_MASK (1 << 28)
 
 typedef struct _DummyDispatch DummyDispatch;
+typedef enum _SignalType SignalType;
 
 struct _DummyDispatch
 {
@@ -56,24 +63,46 @@ GCond *atk_bridge_cond;
 GMutex *key_dispatch_mutex;
 GCond *key_dispatch_cond;
 
-static gint key_dispatch_result = KEY_DISPATCH_NOT_DISPATCHED;
+static gint key_dispatch_result;
 static gboolean (*origin_g_idle_dispatch) (GSource*, GSourceFunc, gpointer);
+static GMainLoop* jni_main_loop;
 
-static GModule* module_atk_bridge = NULL;
+gpointer current_bridge_data = NULL;
+JavaVM* cachedJVM;
+JNIEnv *cachedEnv;
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *javaVM, void *reserve)
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserve)
 {
   JNIEnv *env;
-  globalJvm = javaVM;
-
-  if ((*javaVM)->GetEnv(javaVM, (void **)&env, JNI_VERSION_1_2))
-  {
-    return JNI_ERR; /* Not supported */
+  cachedJVM = jvm;
+  if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_8)) {
+    fprintf(stderr, "Attach failed\n");
+    return JNI_ERR; /* JNI version not supported */
   }
-  return JNI_VERSION_1_2;
+  g_assert(jvm != NULL);
+
+  return JNI_VERSION_1_8;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserve) {
 }
 
-JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *javaVM, void *reserve) {
+gboolean jaw_accessibility_init (void *data)
+{
+  g_mutex_lock(atk_bridge_mutex);
+  atk_bridge_adaptor_init (NULL, NULL);
+  if (jaw_debug)
+    g_print ("Atk Accessibility bridge initialized\n");
+  g_cond_signal(atk_bridge_cond);
+  g_mutex_unlock(atk_bridge_mutex);
+
+  return TRUE;
+}
+
+void
+jaw_accessibility_shutdown (void)
+{
+  atk_bridge_adaptor_cleanup();
 }
 
 static gboolean
@@ -104,32 +133,16 @@ jaw_idle_dispatch (GSource *source,
   return origin_g_idle_dispatch(source, callback, user_data);
 }
 
-static void jaw_exit_func ()
-{
-  _exit(0);
-}
 
-static gboolean
-jaw_load_atk_bridge (gpointer p)
+static
+void *jni_loop_callback(void *data)
 {
-  g_mutex_lock(atk_bridge_mutex);
-  atk_bridge_adaptor_init (NULL, NULL);
-
+  char *message;
+  message = (char *)data;
   if (jaw_debug)
-    printf("ATK Bridge has been loaded successfully\n");
-
-  atexit( jaw_exit_func );
-
-  g_cond_signal(atk_bridge_cond);
-  g_mutex_unlock(atk_bridge_mutex);
-
-  return FALSE;
-}
-
-gpointer jni_main_loop(gpointer data)
-{
-  g_main_loop_run( (GMainLoop*)data );
-  return NULL;
+    printf("%s \n", message);
+  g_main_loop_quit (jni_main_loop);
+  return 0;
 }
 
 JNIEXPORT jboolean
@@ -164,15 +177,18 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_initNativeLibrary(JNIEnv *jniEnv
   }
 
   jaw_impl_init_mutex();
-
+  g_assert (atk_bridge_mutex == NULL);
   atk_bridge_mutex = g_new(GMutex, 1);
   g_mutex_init(atk_bridge_mutex);
+  g_assert (atk_bridge_mutex != NULL);
 
   atk_bridge_cond = g_new(GCond, 1);
   g_cond_init(atk_bridge_cond);
 
+  g_assert (key_dispatch_mutex == NULL);
   key_dispatch_mutex = g_new(GMutex, 1);
   g_mutex_init(key_dispatch_mutex);
+  g_assert (key_dispatch_mutex != NULL);
 
   key_dispatch_cond = g_new(GCond, 1);
   g_cond_init(key_dispatch_cond);
@@ -191,28 +207,31 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_loadAtkBridge(JNIEnv *jniEnv,
   // Enable ATK Bridge so we can load it now
   g_setenv("NO_AT_BRIDGE", "0", TRUE);
 
-  const gchar *name = "loaded-bridge";
-  GMainLoop *main_loop = g_main_loop_new( NULL, FALSE );
-
-  g_idle_add(jaw_load_atk_bridge, NULL);
+  GThread *thread;
+  GError *err;
+  char * message;
+  message = "jni main loop";
+  err = NULL;
 
-  // We need to wait for the completion of the loading of ATK Bridge
-  // in order to ensure event listeners in ATK Bridge are properly
-  // registered before any emission of AWT event.
-  g_mutex_lock(atk_bridge_mutex);
-
-  GThread *main_loop_thread = g_thread_new(name,
-                                           jni_main_loop,
-                                           (gpointer)main_loop);
+  jni_main_loop = g_main_loop_new (NULL, FALSE);
+  g_idle_add((GSourceFunc)jaw_accessibility_init, NULL);
 
-  g_cond_wait(atk_bridge_cond, atk_bridge_mutex);
+  thread = g_thread_new(message, (GThreadFunc)jni_loop_callback, (void *)message);
+  if(thread == NULL)
+  {
+    if (jaw_debug)
+    {
+      printf("Thread create failed: %s!!\n", err->message );
+      g_error_free (err);
+    }
+  }
 
-  g_mutex_unlock(atk_bridge_mutex);
-  g_mutex_clear(atk_bridge_mutex);
-  g_free(atk_bridge_mutex);
+  g_main_loop_run(jni_main_loop);
+  g_thread_join (thread);
+  g_main_loop_unref(jni_main_loop);
 }
 
-typedef enum _SignalType {
+enum _SignalType {
   Sig_Text_Caret_Moved = 0,
   Sig_Text_Property_Changed_Insert = 1,
   Sig_Text_Property_Changed_Delete = 2,
@@ -235,7 +254,7 @@ typedef enum _SignalType {
   Sig_Object_Property_Change_Accessible_Table_Row_Description = 19,
   Sig_Table_Model_Changed = 20,
   Sig_Text_Property_Changed = 21
-}SignalType;
+};
 
 typedef struct _CallbackPara {
   jobject global_ac;
@@ -285,7 +304,7 @@ focus_notify_handler (gpointer p)
   }
 
   AtkObject* atk_obj = ATK_OBJECT(jaw_impl);
-  atk_object_notify_state_change(atk_obj, ATK_STATE_FOCUSED, para->state_value);
+  atk_object_notify_state_change(atk_obj, ATK_STATE_FOCUSED, TRUE);
 
   free_callback_para(para);
 
@@ -311,7 +330,7 @@ window_open_handler (gpointer p)
   gboolean is_toplevel = para->is_toplevel;
 
   JNIEnv *jniEnv = jaw_util_get_jni_env();
-  JawImpl* jaw_impl = jaw_impl_find_instance(jniEnv, global_ac);
+  JawImpl* jaw_impl = jaw_impl_get_instance(jniEnv, global_ac);
   AtkObject* atk_obj = ATK_OBJECT(jaw_impl);
 
   if (!g_strcmp0(atk_role_get_name(atk_object_get_role(atk_obj)),
@@ -531,7 +550,7 @@ window_activate_handler (gpointer p)
   jobject global_ac = para->global_ac;
 
   JNIEnv *jniEnv = jaw_util_get_jni_env();
-  JawImpl* jaw_impl = jaw_impl_find_instance(jniEnv, global_ac);
+  JawImpl* jaw_impl = jaw_impl_get_instance(jniEnv, global_ac);
 
   if (jaw_impl == NULL)
   {
@@ -598,6 +617,7 @@ window_state_change_handler (gpointer p)
   jobject global_ac = para->global_ac;
 
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+
   JawImpl* jaw_impl = jaw_impl_get_instance(jniEnv, global_ac);
 
   if (jaw_impl == NULL)
@@ -787,10 +807,24 @@ signal_emit_handler (gpointer p)
       gint newValue = get_int_value(jniEnv,
                                     (*jniEnv)->GetObjectArrayElement(jniEnv, args, 1));
       AtkPropertyValues values = { NULL };
+         // GValues must be initialized
+
+      g_assert (!G_VALUE_HOLDS_INT (&values.old_value));
       g_value_init(&values.old_value, G_TYPE_INT);
+      g_assert (G_VALUE_HOLDS_INT (&values.old_value));
       g_value_set_int(&values.old_value, oldValue);
+      if (jaw_debug)
+        printf ("%d\n", g_value_get_int(&values.old_value));
+      g_value_unset(&values.old_value);
+
+      g_assert (!G_VALUE_HOLDS_INT (&values.new_value));
       g_value_init(&values.new_value, G_TYPE_INT);
+      g_assert (G_VALUE_HOLDS_INT (&values.old_value));
       g_value_set_int(&values.new_value, newValue);
+      if (jaw_debug)
+        printf ("%d\n", g_value_get_int(&values.new_value));
+      g_value_unset(&values.new_value);
+
       values.property_name = "accessible-actions";
 
       g_signal_emit_by_name(atk_obj,
@@ -875,7 +909,7 @@ signal_emit_handler (gpointer p)
       gint newValue = get_int_value(jniEnv,
                                     (*jniEnv)->GetObjectArrayElement(jniEnv, args, 0));
 
-      gint prevCount = *(gint*)g_hash_table_lookup(jaw_obj->storedData,
+      gint prevCount = (gint)g_hash_table_lookup(jaw_obj->storedData,
                                                    "Previous_Count");
       gint curCount = atk_text_get_character_count(ATK_TEXT(jaw_obj));
 
@@ -1040,9 +1074,13 @@ static gboolean
 key_dispatch_handler (gpointer p)
 {
   g_mutex_lock(key_dispatch_mutex);
+  JavaVM *jvm;
+  jvm = cachedJVM;
 
   jobject jAtkKeyEvent = (jobject)p;
   JNIEnv *jniEnv = jaw_util_get_jni_env();
+  key_dispatch_result = 0;
+  cachedEnv = jniEnv;
 
   AtkKeyEventStruct *event = g_new0(AtkKeyEventStruct, 1);
   jclass classAtkKeyEvent = (*jniEnv)->FindClass(jniEnv, "org/GNOME/Accessibility/AtkKeyEvent");
@@ -1108,18 +1146,23 @@ key_dispatch_handler (gpointer p)
   jfieldID jfidTimestamp = (*jniEnv)->GetFieldID(jniEnv, classAtkKeyEvent, "timestamp", "I");
   event->timestamp = (guint32)(*jniEnv)->GetIntField(jniEnv, jAtkKeyEvent, jfidTimestamp);
 
+  if(jaw_debug)
+    printf("key_dispatch_result = %d\n ",key_dispatch_result);
   gboolean b = jaw_util_dispatch_key_event (event);
+  if(jaw_debug)
+    printf("b = %s\n ",(char *)&b);
   if (b) {
-    key_dispatch_result = KEY_DISPATCH_CONSUMED;
+    key_dispatch_result = 1;
   } else {
-    key_dispatch_result = KEY_DISPATCH_NOT_CONSUMED;
+    key_dispatch_result = 2;
   }
-
+  if(jaw_debug)
+    printf("key_dispatch_result = %d\n ",key_dispatch_result);
   (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, event->string);
   g_free(event);
 
   (*jniEnv)->DeleteGlobalRef(jniEnv, jAtkKeyEvent);
-
+  (*jvm)->DetachCurrentThread(jvm);
   g_cond_signal(key_dispatch_cond);
   g_mutex_unlock(key_dispatch_mutex);
   return FALSE;
@@ -1131,17 +1174,20 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_dispatchKeyEvent(JNIEnv *jniEnv,
                                                                  jobject jAtkKeyEvent)
 {
   jboolean key_consumed;
+  cachedEnv = jniEnv;
   jobject global_key_event = (*jniEnv)->NewGlobalRef(jniEnv, jAtkKeyEvent);
 
   g_mutex_lock(key_dispatch_mutex);
 
   g_idle_add(key_dispatch_handler, (gpointer)global_key_event);
 
-  while (key_dispatch_result == KEY_DISPATCH_NOT_DISPATCHED) {
+  if(jaw_debug)
+    printf("key_dispatch_result = %d\n ",key_dispatch_result);
+  while (key_dispatch_result == 0) {
     g_cond_wait(key_dispatch_cond, key_dispatch_mutex);
   }
 
-  if (key_dispatch_result == KEY_DISPATCH_CONSUMED)
+  if (key_dispatch_result == 1)
   {
     key_consumed = JNI_TRUE;
   } else
@@ -1149,12 +1195,14 @@ JNICALL Java_org_GNOME_Accessibility_AtkWrapper_dispatchKeyEvent(JNIEnv *jniEnv,
     key_consumed = JNI_FALSE;
   }
 
-  key_dispatch_result = KEY_DISPATCH_NOT_DISPATCHED;
+  key_dispatch_result = 0;
 
   g_mutex_unlock(key_dispatch_mutex);
-  g_mutex_clear(key_dispatch_mutex);
-  g_free(key_dispatch_mutex);
 
   return key_consumed;
 }
 
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/jni/src/jawutil.c b/jni/src/jawutil.c
index 3fe050d..e8241a3 100644
--- a/jni/src/jawutil.c
+++ b/jni/src/jawutil.c
@@ -57,8 +57,8 @@ struct _JawUtilListenerInfo
        gulong  hook_id;
 };
 
-JavaVM *globalJvm = NULL;
-JNIEnv *globalEnv = NULL;
+JavaVM *cachedJVM;
+JNIEnv *cachedEnv;
 
 GType
 jaw_util_get_type(void)
@@ -398,11 +398,24 @@ jaw_util_is_same_jobject(gconstpointer a,
 }
 
 JNIEnv*
-jaw_util_get_jni_env()
+jaw_util_get_jni_env(void)
 {
-       (*globalJvm)->AttachCurrentThread( globalJvm, (void**)&globalEnv, NULL );
-       
-       return globalEnv;
+  JNIEnv *env;
+  JavaVM *jvm;
+  jvm = cachedJVM;
+  env = cachedEnv;
+  if (jvm == NULL) (*env)->GetJavaVM(globalEnv,&jvm);
+  int res;
+  #ifdef JNI_VERSION_1_8
+    res = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
+  #else
+    (res*) = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
+  #endif
+  if (&res < 0) {
+    fprintf(stderr, "Attach failed\n");
+  }
+
+  return env;
 }
 
 static jobject
diff --git a/wrapper/org/GNOME/Accessibility/AtkKeyEvent.java 
b/wrapper/org/GNOME/Accessibility/AtkKeyEvent.java
index 9bf6348..2db5911 100644
--- a/wrapper/org/GNOME/Accessibility/AtkKeyEvent.java
+++ b/wrapper/org/GNOME/Accessibility/AtkKeyEvent.java
@@ -25,7 +25,7 @@ import java.util.HashMap;
 
 public class AtkKeyEvent {
 
-  private static HashMap<Object,String> nonAlphaNumericMap=null;
+  private static HashMap nonAlphaNumericMap = null;
 
   public static final int ATK_KEY_EVENT_PRESSED = 0;
   public static final int ATK_KEY_EVENT_RELEASED = 1;
@@ -42,6 +42,7 @@ public class AtkKeyEvent {
 
   static {
     // Non-alphanumeric symbols that need to be mapped to X11 keysym names
+    nonAlphaNumericMap = new HashMap( 40 );
     nonAlphaNumericMap.put("!", "exclam");
     nonAlphaNumericMap.put("@", "at");
     nonAlphaNumericMap.put("#", "numbersign");
@@ -135,7 +136,7 @@ public class AtkKeyEvent {
     keycode = e.getKeyCode();
     timestamp = (int)e.getWhen();
 
-    String nonAlphaNumericString = nonAlphaNumericMap.get(string);
+    String nonAlphaNumericString = (String) nonAlphaNumericMap.get(string);
     if (nonAlphaNumericString != null)
       string = nonAlphaNumericString;
   }
@@ -143,7 +144,7 @@ public class AtkKeyEvent {
 
 class GNOMEKeyMapping {
 
-  private static HashMap<Object,Object> keyMap = null;
+  private static HashMap keyMap = null;
 
   public static final class GNOMEKeyInfo {
     private int     gdkKeyCode;
@@ -192,6 +193,7 @@ class GNOMEKeyMapping {
   }
 
   private static void initializeMap() {
+    keyMap = new HashMap( 146 ); // Currently only 110, so allocate 110 / 0.75
 
     keyMap.put( new Integer(KeyEvent.VK_COLON),        new GNOMEKeyInfo( 0x20a1, "ColonSign" ) ); // 
GDK_ColonSign
     keyMap.put( new Integer(KeyEvent.VK_EURO_SIGN),    new GNOMEKeyInfo( 0x20ac, "EuroSign" ) ); // 
GDK_EuroSign


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]