コード例 #1
0
static void CreateHelper(EscalateHelper **helper, GIOChannel **stdin_writer,
                         GIOChannel **stdout_reader) {
  int stdin_fds [2];
  int stdout_fds [2];
  g_assert(g_unix_open_pipe(stdin_fds, 0, NULL));
  g_assert(g_unix_open_pipe(stdout_fds, 0, NULL));

  *helper = EscalateHelperNew(stdin_fds[0], stdout_fds[1]);
  *stdin_writer = g_io_channel_unix_new(stdin_fds[1]);
  *stdout_reader = g_io_channel_unix_new(stdout_fds[0]);

  g_assert(*helper);
}
コード例 #2
0
ファイル: gwakeup.c プロジェクト: alcacoop/libgnubg-android
/**
 * g_wakeup_new:
 *
 * Creates a new #GWakeup.
 *
 * You should use g_wakeup_free() to free it when you are done.
 *
 * Returns: a new #GWakeup
 *
 * Since: 2.30
 **/
GWakeup *
g_wakeup_new (void)
{
    GError *error = NULL;
    GWakeup *wakeup;

    wakeup = g_slice_new (GWakeup);

    /* try eventfd first, if we think we can */
#if defined (HAVE_EVENTFD)
#ifndef TEST_EVENTFD_FALLBACK
    wakeup->fds[0] = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
#else
    wakeup->fds[0] = -1;
#endif

    if (wakeup->fds[0] != -1)
    {
        wakeup->fds[1] = -1;
        return wakeup;
    }

    /* for any failure, try a pipe instead */
#endif

    if (!g_unix_open_pipe (wakeup->fds, FD_CLOEXEC, &error))
        g_error ("Creating pipes for GWakeup: %s\n", error->message);

    if (!g_unix_set_fd_nonblocking (wakeup->fds[0], TRUE, &error) ||
            !g_unix_set_fd_nonblocking (wakeup->fds[1], TRUE, &error))
        g_error ("Set pipes non-blocking for GWakeup: %s\n", error->message);

    return wakeup;
}
コード例 #3
0
static void TestWrite(gconstpointer user_data) {
  guint index = GPOINTER_TO_UINT(user_data);
  gint fds [] = { 0, 0 };
  GIOChannel *reader = NULL;
  GIOChannel *writer = NULL;
  GThread *thread = NULL;
  EscalateMessage *message = NULL;
  GError *error = NULL;
  gboolean success = FALSE;
  gchar *result = NULL;

  g_assert(g_unix_open_pipe(fds, 0, NULL));
  reader = g_io_channel_unix_new(fds[0]);
  writer = g_io_channel_unix_new(fds[1]);

  thread = g_thread_new("Reader", (GThreadFunc) ReaderThread, reader);

  message = EscalateMessageLoad(example_messages[index], NULL);
  g_assert(message);
  success = EscalateMessageWrite(message, writer, &error);
  g_assert_no_error(error);
  g_assert(success);

  g_assert_cmpint(G_IO_STATUS_NORMAL, ==,
                  g_io_channel_shutdown(writer, TRUE, NULL));

  result = (gchar *) g_thread_join(thread);
  result[strlen(result)-1] = '\0';  // Cut off newline.
  g_assert_cmpstr(example_messages[index], ==, result);

  g_io_channel_unref(reader);
  g_io_channel_unref(writer);
  EscalateMessageUnref(message);
  g_free(result);
}
コード例 #4
0
gboolean __wrap_g_spawn_async_with_pipes(const gchar *working_directory,
                                         gchar **argv,
                                         gchar **envp,
                                         GSpawnFlags flags,
                                         GSpawnChildSetupFunc child_setup,
                                         gpointer user_data,
                                         GPid *child_pid,
                                         gint *standard_input,
                                         gint *standard_output,
                                         gint *standard_error,
                                         GError **error) {
  int standard_input_fds [2] = { 0, 0 };
  int standard_output_fds [2] = { 0, 0 };
  pid_t pid = 0;

  g_assert_cmpstr("/", ==, working_directory);
  g_assert(argv);
  g_assert_cmpstr("/usr/bin/pam-escalate-helper", ==, argv[0]);
  g_assert_cmpstr(NULL, ==, argv[1]);
  g_assert(!envp);
  g_assert_cmpint(0, ==, flags);
  g_assert(!child_setup);
  g_assert(!user_data);
  g_assert(child_pid);
  g_assert(standard_input);
  g_assert(standard_output);
  g_assert(!standard_error);

  g_assert(g_unix_open_pipe(standard_input_fds, 0, NULL));
  g_assert(g_unix_open_pipe(standard_output_fds, 0, NULL));

  pid = fork();
  if (pid) {
    close(standard_input_fds[0]);
    close(standard_output_fds[1]);
    *child_pid = pid;
    *standard_input = standard_input_fds[1];
    *standard_output = standard_output_fds[0];
    return TRUE;
  } else {
    close(standard_input_fds[1]);
    close(standard_output_fds[0]);
    exit(EscalateTestMockHelperProcess(standard_input_fds[0],
                                       standard_output_fds[1]));
  }
}
コード例 #5
0
static void TestRead(gconstpointer user_data) {
  guint index = GPOINTER_TO_UINT(user_data);
  gint fds [] = { 0, 0 };
  GIOChannel *reader = NULL;
  WriterThreadContext thread_ctx = { NULL, NULL };
  GThread *thread = NULL;
  GError *error = NULL;
  EscalateMessage *message = NULL;
  GVariant *expected_values = CreateExampleMessageValues(index);

  g_assert(g_unix_open_pipe(fds, 0, NULL));
  reader = g_io_channel_unix_new(fds[0]);

  thread_ctx.channel = g_io_channel_unix_new(fds[1]);
  thread_ctx.contents = example_messages[index];
  thread = g_thread_new("Writer", (GThreadFunc) WriterThread, &thread_ctx);
  g_assert(thread);

  message = EscalateMessageRead(reader, &error);
  g_assert_no_error(error);
  g_assert(message);
  g_assert_cmpint(EscalateMessageGetType(message), ==,
                  example_message_types[index]);
  g_assert(g_variant_equal(expected_values, message->values));
  EscalateMessageUnref(message);

  message = EscalateMessageRead(reader, &error);
  g_assert_error(error, ESCALATE_MESSAGE_ERROR, ESCALATE_MESSAGE_ERROR_EOF);
  g_assert(!message);
  g_error_free(error);

  g_thread_join(thread);
  g_variant_unref(expected_values);
  g_io_channel_shutdown(reader, FALSE, NULL);
  g_io_channel_unref(reader);
  g_io_channel_unref(thread_ctx.channel);
}
コード例 #6
0
ファイル: gdkselection-wayland.c プロジェクト: 3v1n0/gtk
void
_gdk_wayland_display_convert_selection (GdkDisplay *display,
					GdkWindow  *requestor,
					GdkAtom     selection,
					GdkAtom     target,
					guint32     time)
{
  GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
  SelectionBuffer *buffer_data;

  if (!wayland_selection->offer)
    {
      GdkEvent *event;

      event = gdk_event_new (GDK_SELECTION_NOTIFY);
      event->selection.window = g_object_ref (requestor);
      event->selection.send_event = FALSE;
      event->selection.selection = selection;
      event->selection.target = target;
      event->selection.property = GDK_NONE;
      event->selection.time = GDK_CURRENT_TIME;
      event->selection.requestor = g_object_ref (requestor);

      gdk_event_put (event);
      gdk_event_free (event);
      return;
    }

  wl_data_offer_accept (wayland_selection->offer,
                        _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
                        gdk_atom_name (target));

  buffer_data = g_hash_table_lookup (wayland_selection->selection_buffers,
                                     target);

  if (buffer_data)
    selection_buffer_add_requestor (buffer_data, requestor);
  else
    {
      GInputStream *stream = NULL;
      int pipe_fd[2], natoms = 0;
      GdkAtom *atoms = NULL;

      if (target == gdk_atom_intern_static_string ("TARGETS"))
        {
          gint i = 0;
          GList *l;

          natoms = g_list_length (wayland_selection->targets);
          atoms = g_new0 (GdkAtom, natoms);

          for (l = wayland_selection->targets; l; l = l->next)
            atoms[i++] = l->data;
        }
      else
        {
          g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL);
          wl_data_offer_receive (wayland_selection->offer,
                                 gdk_atom_name (target),
                                 pipe_fd[1]);
          stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
          close (pipe_fd[1]);
        }

      buffer_data = selection_buffer_new (stream, selection, target);
      selection_buffer_add_requestor (buffer_data, requestor);

      if (stream)
        g_object_unref (stream);

      if (atoms)
        {
          /* Store directly the local atoms */
          selection_buffer_append_data (buffer_data, atoms, natoms * sizeof (GdkAtom));
          g_free (atoms);
        }

      g_hash_table_insert (wayland_selection->selection_buffers,
                           GDK_ATOM_TO_POINTER (target),
                           buffer_data);
    }

  if (!buffer_data->stream)
    selection_buffer_notify (buffer_data);
}
コード例 #7
0
ファイル: gdm-x-session.c プロジェクト: zhulianhai/gdm
static gboolean
spawn_bus (State        *state,
           GCancellable *cancellable)
{
        GPtrArray           *arguments = NULL;
        GSubprocessLauncher *launcher = NULL;
        GSubprocess         *subprocess = NULL;
        GInputStream        *input_stream = NULL;
        GDataInputStream    *data_stream = NULL;
        GError              *error = NULL;
        const char          *bus_env = NULL;
        char                *bus_address_fd_string;
        char                *bus_address = NULL;
        gsize                bus_address_size;

        gboolean  is_running = FALSE;
        int       ret;
        int       pipe_fds[2];

        g_debug ("Running session message bus");

        bus_env = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
        if (bus_env != NULL) {
                g_debug ("session message bus already running, not starting another one");
                state->bus_address = g_strdup (bus_env);
                return TRUE;
        }

        ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);

        if (!ret) {
                g_debug ("could not open pipe: %s", error->message);
                goto out;
        }

        arguments = g_ptr_array_new ();
        launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);

        g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE);
        g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE);

        g_subprocess_launcher_take_fd (launcher, pipe_fds[1], BUS_ADDRESS_FILENO);

        bus_address_fd_string = g_strdup_printf ("%d", BUS_ADDRESS_FILENO);

        g_ptr_array_add (arguments, "dbus-daemon");

        g_ptr_array_add (arguments, "--print-address");
        g_ptr_array_add (arguments, bus_address_fd_string);
        g_ptr_array_add (arguments, "--session");
        g_ptr_array_add (arguments, NULL);

        subprocess = g_subprocess_launcher_spawnv (launcher,
                                                   (const char * const *) arguments->pdata,
                                                   &error);
        g_free (bus_address_fd_string);
        g_clear_object (&launcher);
        g_ptr_array_free (arguments, TRUE);

        if (subprocess == NULL) {
                g_debug ("could not start dbus-daemon: %s", error->message);
                goto out;
        }

        input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
        data_stream = g_data_input_stream_new (input_stream);
        g_clear_object (&input_stream);

        bus_address = g_data_input_stream_read_line (data_stream,
                                                     &bus_address_size,
                                                     cancellable,
                                                     &error);

        if (error != NULL) {
                g_debug ("could not read address from session message bus: %s", error->message);
                goto out;
        }

        if (bus_address == NULL) {
                g_debug ("session message bus did not write address");
                goto out;
        }

        state->bus_address = bus_address;

        state->bus_subprocess = g_object_ref (subprocess);

        g_subprocess_wait_async (state->bus_subprocess,
                                 cancellable,
                                 (GAsyncReadyCallback)
                                 on_bus_finished,
                                 state);

        is_running = TRUE;
out:
        g_clear_object (&data_stream);
        g_clear_object (&subprocess);
        g_clear_object (&launcher);
        g_clear_error (&error);

        return is_running;
}
コード例 #8
0
ファイル: gdm-x-session.c プロジェクト: zhulianhai/gdm
static gboolean
spawn_x_server (State        *state,
                gboolean      allow_remote_connections,
                GCancellable *cancellable)
{
        GPtrArray           *arguments = NULL;
        GSubprocessLauncher *launcher = NULL;
        GSubprocess         *subprocess = NULL;
        GInputStream        *input_stream = NULL;
        GDataInputStream    *data_stream = NULL;
        GError              *error = NULL;

        char     *auth_file;
        gboolean  is_running = FALSE;
        int       ret;
        int       pipe_fds[2];
        char     *display_fd_string = NULL;
        char     *vt_string = NULL;
        char     *display_number;
        gsize     display_number_size;

        auth_file = prepare_auth_file ();

        g_debug ("Running X server");

        ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);

        if (!ret) {
                g_debug ("could not open pipe: %s", error->message);
                goto out;
        }

        arguments = g_ptr_array_new ();
        launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_INHERIT);
        g_subprocess_launcher_setenv (launcher, "XORG_RUN_AS_USER_OK", "1", TRUE);
        g_subprocess_launcher_take_fd (launcher, pipe_fds[1], DISPLAY_FILENO);

        if (g_getenv ("XDG_VTNR") != NULL) {
                int vt;

                vt = atoi (g_getenv ("XDG_VTNR"));

                if (vt > 0 && vt < 64) {
                        vt_string = g_strdup_printf ("vt%d", vt);
                }
        }

        display_fd_string = g_strdup_printf ("%d", DISPLAY_FILENO);

        g_ptr_array_add (arguments, X_SERVER);

        if (vt_string != NULL) {
                g_ptr_array_add (arguments, vt_string);
        }

        g_ptr_array_add (arguments, "-displayfd");
        g_ptr_array_add (arguments, display_fd_string);

        g_ptr_array_add (arguments, "-auth");
        g_ptr_array_add (arguments, auth_file);

        /* If we were compiled with Xserver >= 1.17 we need to specify
         * '-listen tcp' as the X server dosen't listen on tcp sockets
         * by default anymore. In older versions we need to pass
         * -nolisten tcp to disable listening on tcp sockets.
         */
#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY
        if (allow_remote_connections) {
                g_ptr_array_add (arguments, "-listen");
                g_ptr_array_add (arguments, "tcp");
        }
#else
        if (!allow_remote_connections) {
                g_ptr_array_add (arguments, "-nolisten");
                g_ptr_array_add (arguments, "tcp");
        }
#endif

        g_ptr_array_add (arguments, "-background");
        g_ptr_array_add (arguments, "none");

        g_ptr_array_add (arguments, "-noreset");
        g_ptr_array_add (arguments, "-keeptty");

        g_ptr_array_add (arguments, "-verbose");
        if (state->debug_enabled) {
                g_ptr_array_add (arguments, "7");
        } else {
                g_ptr_array_add (arguments, "3");
        }

        if (state->debug_enabled) {
                g_ptr_array_add (arguments, "-core");
        }
        g_ptr_array_add (arguments, NULL);

        subprocess = g_subprocess_launcher_spawnv (launcher,
                                                   (const char * const *) arguments->pdata,
                                                   &error);
        g_free (display_fd_string);
        g_clear_object (&launcher);
        g_ptr_array_free (arguments, TRUE);

        if (subprocess == NULL) {
                g_debug ("could not start X server: %s", error->message);
                goto out;
        }

        input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
        data_stream = g_data_input_stream_new (input_stream);
        g_clear_object (&input_stream);

        display_number = g_data_input_stream_read_line (data_stream,
                                                        &display_number_size,
                                                        cancellable,
                                                        &error);

        if (error != NULL) {
                g_debug ("could not read display string from X server: %s", error->message);
                goto out;
        }

        if (display_number == NULL) {
                g_debug ("X server did not write display string");
                goto out;
        }

        state->display_name = g_strdup_printf (":%s", display_number);
        g_clear_pointer (&display_number, g_free);

        state->auth_file = g_strdup (auth_file);
        state->x_subprocess = g_object_ref (subprocess);

        g_subprocess_wait_async (state->x_subprocess,
                                 cancellable,
                                 (GAsyncReadyCallback)
                                 on_x_server_finished,
                                 state);

        is_running = TRUE;
out:
        g_clear_pointer (&auth_file, g_free);
        g_clear_object (&data_stream);
        g_clear_object (&subprocess);
        g_clear_object (&launcher);
        g_clear_error (&error);

        return is_running;
}
コード例 #9
0
ファイル: gtester.c プロジェクト: endlessm/glib
static gboolean
launch_test_binary (const char *binary,
                    guint       skip_tests)
{
  GTestLogBuffer *tlb;
  GSList *slist, *free_list = NULL;
  GError *error = NULL;
  int argc = 0;
  const gchar **argv;
  GPid pid = 0;
  gint report_pipe[2] = { -1, -1 };
  guint child_report_cb_id = 0;
  gboolean loop_pending;
  gint i = 0;

  if (!g_unix_open_pipe (report_pipe, FD_CLOEXEC, &error))
    {
      if (subtest_mode_fatal)
        g_error ("Failed to open pipe for test binary: %s: %s", binary, error->message);
      else
        g_warning ("Failed to open pipe for test binary: %s: %s", binary, error->message);
      g_clear_error (&error);
      return FALSE;
    }

  /* setup argc */
  for (slist = subtest_args; slist; slist = slist->next)
    argc++;
  /* argc++; */
  if (subtest_quiet)
    argc++;
  if (subtest_verbose)
    argc++;
  if (!subtest_mode_fatal)
    argc++;
  /* Either -m=quick or -m=slow is always appended. */
  argc++;
  if (subtest_mode_perf)
    argc++;
  if (!subtest_mode_undefined)
    argc++;
  if (gtester_list_tests)
    argc++;
  if (subtest_seedstr)
    argc++;
  argc++;
  if (skip_tests)
    argc++;
  for (slist = subtest_paths; slist; slist = slist->next)
    argc++;
  for (slist = skipped_paths; slist; slist = slist->next)
    argc++;

  /* setup argv */
  argv = g_malloc ((argc + 2) * sizeof(gchar *));
  argv[i++] = binary;
  for (slist = subtest_args; slist; slist = slist->next)
    argv[i++] = (gchar*) slist->data;
  /* argv[i++] = "--debug-log"; */
  if (subtest_quiet)
    argv[i++] = "--quiet";
  if (subtest_verbose)
    argv[i++] = "--verbose";
  if (!subtest_mode_fatal)
    argv[i++] = "--keep-going";
  if (subtest_mode_quick)
    argv[i++] = "-m=quick";
  else
    argv[i++] = "-m=slow";
  if (subtest_mode_perf)
    argv[i++] = "-m=perf";
  if (!subtest_mode_undefined)
    argv[i++] = "-m=no-undefined";
  if (gtester_list_tests)
    argv[i++] = "-l";
  if (subtest_seedstr)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
  argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
  if (skip_tests)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests));
  for (slist = subtest_paths; slist; slist = slist->next)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
  for (slist = skipped_paths; slist; slist = slist->next)
    argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-s=%s", (gchar*) slist->data));
  argv[i++] = NULL;

  g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
                            (gchar**) argv,
                            NULL, /* envp */
                            G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
                            unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
                            &pid,
                            NULL,       /* standard_input */
                            NULL,       /* standard_output */
                            NULL,       /* standard_error */
                            &error);
  g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
  g_slist_free (free_list);
  free_list = NULL;
  close (report_pipe[1]);

  if (!gtester_quiet)
    g_print ("(pid=%lu)\n", (unsigned long) pid);

  if (error)
    {
      close (report_pipe[0]);
      if (subtest_mode_fatal)
        g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
      else
        g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
      g_clear_error (&error);
      g_free (argv);
      return FALSE;
    }
  g_free (argv);

  subtest_running = TRUE;
  subtest_io_pending = TRUE;
  tlb = g_test_log_buffer_new();
  if (report_pipe[0] >= 0)
    {
      ioc_report = g_io_channel_unix_new (report_pipe[0]);
      g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
      g_io_channel_set_encoding (ioc_report, NULL, NULL);
      g_io_channel_set_buffered (ioc_report, FALSE);
      child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
      g_io_channel_unref (ioc_report);
    }
  g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);

  loop_pending = g_main_context_pending (NULL);
  while (subtest_running ||     /* FALSE once child exits */
         subtest_io_pending ||  /* FALSE once ioc_report closes */
         loop_pending)          /* TRUE while idler, etc are running */
    {
      /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */
      /* check for unexpected hangs that are not signalled on report_pipe */
      if (!subtest_running &&   /* child exited */
          subtest_io_pending && /* no EOF detected on report_pipe */
          !loop_pending)        /* no IO events pending however */
        break;
      g_main_context_iteration (NULL, TRUE);
      loop_pending = g_main_context_pending (NULL);
    }

  if (subtest_io_pending)
    g_source_remove (child_report_cb_id);

  close (report_pipe[0]);
  g_test_log_buffer_free (tlb);

  return TRUE;
}
コード例 #10
0
ファイル: gdbus-close-pending.c プロジェクト: GNOME/glib
static void
test_once (Fixture       *f,
           gconstpointer  context)
{
  GDBusMessage *message;
  gboolean pipe_res;

  pipe_res = g_unix_open_pipe (f->server_to_client, FD_CLOEXEC, &f->error);
  g_assert (pipe_res);
  pipe_res = g_unix_open_pipe (f->client_to_server, FD_CLOEXEC, &f->error);
  g_assert (pipe_res);

  f->server_iostream = my_io_stream_new_for_fds (f->client_to_server[0],
                                                 f->server_to_client[1]);
  f->iostream = my_io_stream_new_for_fds (f->server_to_client[0],
                                          f->client_to_server[1]);

  g_dbus_connection_new (f->server_iostream,
                         f->guid,
                         (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER |
                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
                         NULL /* auth observer */,
                         NULL /* cancellable */,
                         on_new_conn, &f->server_conn);

  g_dbus_connection_new (f->iostream,
                         NULL,
                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
                         NULL /* auth observer */,
                         NULL /* cancellable */,
                         on_new_conn, &f->connection);

  while (f->server_conn == NULL || f->connection == NULL)
    g_main_context_iteration (NULL, TRUE);

  /*
   * queue a message - it'll sometimes be sent while the close is pending,
   * triggering the bug
   */
  message = g_dbus_message_new_signal ("/", "com.example.Foo", "Bar");
  g_dbus_connection_send_message (f->connection, message, 0, NULL, &f->error);
  g_assert_no_error (f->error);
  g_object_unref (message);

  /* close the connection (deliberately or via last-unref) */
  if (g_strcmp0 (context, "unref") == 0)
    {
      g_clear_object (&f->connection);
    }
  else
    {
      g_dbus_connection_close_sync (f->connection, NULL, &f->error);
      g_assert_no_error (f->error);
    }

  /* either way, wait for the connection to close */
  while (!g_dbus_connection_is_closed (f->server_conn))
    g_main_context_iteration (NULL, TRUE);

  /* clean up before the next run */
  g_clear_object (&f->iostream);
  g_clear_object (&f->server_iostream);
  g_clear_object (&f->connection);
  g_clear_object (&f->server_conn);
  g_clear_error (&f->error);
}
コード例 #11
0
ファイル: gdkselection-wayland.c プロジェクト: endlessm/gtk
void
_gdk_wayland_display_convert_selection (GdkDisplay *display,
                                        GdkWindow  *requestor,
                                        GdkAtom     selection,
                                        GdkAtom     target,
                                        guint32     time)
{
  GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display);
  const SelectionData *selection_data;
  SelectionBuffer *buffer_data;
  gpointer offer;
  gchar *mimetype;
  GList *target_list;

  selection_data = selection_lookup_offer_by_atom (wayland_selection, selection);
  if (!selection_data)
    return;

  offer = gdk_wayland_selection_get_offer (display, selection);
  target_list = gdk_wayland_selection_get_targets (display, selection);

  if (!offer || target == gdk_atom_intern_static_string ("DELETE"))
    {
      emit_empty_selection_notify (requestor, selection, target);
      return;
    }

  mimetype = gdk_atom_name (target);

  if (target != gdk_atom_intern_static_string ("TARGETS"))
    {
      if (!g_list_find (target_list, GDK_ATOM_TO_POINTER (target)))
        {
          emit_empty_selection_notify (requestor, selection, target);
          return;
        }

      if (selection != atoms[ATOM_PRIMARY])
        wl_data_offer_accept (offer,
                              _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)),
                              mimetype);
    }

  buffer_data = g_hash_table_lookup (selection_data->buffers, target);

  if (buffer_data)
    selection_buffer_add_requestor (buffer_data, requestor);
  else
    {
      GInputStream *stream = NULL;
      int pipe_fd[2], natoms = 0;
      GdkAtom *targets = NULL;

      if (target == gdk_atom_intern_static_string ("TARGETS"))
        {
          gint i = 0;
          GList *l;

          natoms = g_list_length (target_list);
          targets = g_new0 (GdkAtom, natoms);

          for (l = target_list; l; l = l->next)
            targets[i++] = l->data;
        }
      else
        {
          g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL);

          if (selection == atoms[ATOM_PRIMARY])
            gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]);
          else
            wl_data_offer_receive (offer, mimetype, pipe_fd[1]);

          stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
          close (pipe_fd[1]);
        }

      buffer_data = selection_buffer_new (stream, selection, target);
      selection_buffer_add_requestor (buffer_data, requestor);

      if (stream)
        g_object_unref (stream);

      if (targets)
        {
          /* Store directly the local atoms */
          selection_buffer_append_data (buffer_data, targets, natoms * sizeof (GdkAtom));
          g_free (targets);
        }

      g_hash_table_insert (selection_data->buffers,
                           GDK_ATOM_TO_POINTER (target),
                           buffer_data);
    }

  if (!buffer_data->stream)
    selection_buffer_notify (buffer_data);

  g_free (mimetype);
}