~ubuntu-branches/ubuntu/trusty/fcitx/trusty

« back to all changes in this revision

Viewing changes to .pc/0001-increase-dbus-max-retry-times.patch/src/module/dbus/dbusstuff.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2012-05-12 01:37:19 UTC
  • mfrom: (10.1.19 sid)
  • Revision ID: package-import@ubuntu.com-20120512013719-qivlvp3gxi4l7z9j
Tags: 1:4.2.3-2
debian/patches/0004-upstream-post-release-changes.patch:
Add upstream fix for testpinyin, to avoid its segfaults.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2010~2010 by CSSlayer                                   *
3
 
 *   wengxt@gmail.com                                                      *
4
 
 *                                                                         *
5
 
 *   This program is free software; you can redistribute it and/or modify  *
6
 
 *   it under the terms of the GNU General Public License as published by  *
7
 
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 
 *   (at your option) any later version.                                   *
9
 
 *                                                                         *
10
 
 *   This program is distributed in the hope that it will be useful,       *
11
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 
 *   GNU General Public License for more details.                          *
14
 
 *                                                                         *
15
 
 *   You should have received a copy of the GNU General Public License     *
16
 
 *   along with this program; if not, write to the                         *
17
 
 *   Free Software Foundation, Inc.,                                       *
18
 
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
19
 
 ***************************************************************************/
20
 
 
21
 
#include <unistd.h>
22
 
#include <dbus/dbus.h>
23
 
#include <libintl.h>
24
 
 
25
 
#include "fcitx/fcitx.h"
26
 
#include "fcitx/module.h"
27
 
#include "fcitx-utils/utarray.h"
28
 
#include "fcitx/instance.h"
29
 
#include "fcitx-utils/log.h"
30
 
#include "fcitx-utils/utils.h"
31
 
 
32
 
#include "frontend/ipc/ipc.h"
33
 
#include "dbusstuff.h"
34
 
 
35
 
 
36
 
typedef struct _FcitxDBusWatch {
37
 
    DBusWatch *watch;
38
 
    struct _FcitxDBusWatch *next;
39
 
} FcitxDBusWatch;
40
 
 
41
 
typedef struct _FcitxDBus {
42
 
    DBusConnection *conn;
43
 
    FcitxInstance* owner;
44
 
    FcitxDBusWatch* watches;
45
 
} FcitxDBus;
46
 
 
47
 
#define RETRY_INTERVAL 2
48
 
#define MAX_RETRY_TIMES 5
49
 
 
50
 
static void* DBusCreate(FcitxInstance* instance);
51
 
static void DBusSetFD(void* arg);
52
 
static void DBusProcessEvent(void* arg);
53
 
static void* DBusGetConnection(void* arg, FcitxModuleFunctionArg args);
54
 
static dbus_bool_t FcitxDBusAddWatch(DBusWatch *watch, void *data);
55
 
static void FcitxDBusRemoveWatch(DBusWatch *watch, void *data);
56
 
 
57
 
FCITX_EXPORT_API
58
 
FcitxModule module = {
59
 
    DBusCreate,
60
 
    DBusSetFD,
61
 
    DBusProcessEvent,
62
 
    NULL,
63
 
    NULL
64
 
};
65
 
 
66
 
FCITX_EXPORT_API
67
 
int ABI_VERSION = FCITX_ABI_VERSION;
68
 
 
69
 
void* DBusCreate(FcitxInstance* instance)
70
 
{
71
 
    FcitxDBus *dbusmodule = (FcitxDBus*) fcitx_utils_malloc0(sizeof(FcitxDBus));
72
 
    FcitxAddon* dbusaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_DBUS_NAME);
73
 
    DBusError err;
74
 
 
75
 
    dbus_threads_init_default();
76
 
 
77
 
    // first init dbus
78
 
    dbus_error_init(&err);
79
 
 
80
 
    int retry = 0;
81
 
    DBusConnection* conn = NULL;
82
 
 
83
 
    do {
84
 
        conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
85
 
        if (dbus_error_is_set(&err)) {
86
 
            FcitxLog(WARNING, _("Connection Error (%s)"), err.message);
87
 
            dbus_error_free(&err);
88
 
            dbus_error_init(&err);
89
 
        }
90
 
 
91
 
        if (NULL == conn) {
92
 
            sleep(RETRY_INTERVAL * MAX_RETRY_TIMES);
93
 
            retry ++;
94
 
        }
95
 
    } while (NULL == conn && retry < MAX_RETRY_TIMES);
96
 
 
97
 
    if (NULL == conn) {
98
 
        free(dbusmodule);
99
 
        return NULL;
100
 
    }
101
 
 
102
 
    if (!dbus_connection_set_watch_functions(conn, FcitxDBusAddWatch, FcitxDBusRemoveWatch,
103
 
            NULL, dbusmodule, NULL)) {
104
 
        FcitxLog(WARNING, _("Add Watch Function Error"));
105
 
        dbus_error_free(&err);
106
 
        free(dbusmodule);
107
 
        return NULL;
108
 
    }
109
 
 
110
 
    dbusmodule->conn = conn;
111
 
    dbusmodule->owner = instance;
112
 
 
113
 
    boolean request_retry = false;
114
 
    char* servicename = NULL;
115
 
    asprintf(&servicename, "%s-%d", FCITX_DBUS_SERVICE, fcitx_utils_get_display_number());
116
 
    do {
117
 
        request_retry = false;
118
 
 
119
 
        // request a name on the bus
120
 
        int ret = dbus_bus_request_name(conn, servicename,
121
 
                                        DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_DO_NOT_QUEUE,
122
 
                                        &err);
123
 
        if (dbus_error_is_set(&err)) {
124
 
            FcitxLog(WARNING, _("Name Error (%s)"), err.message);
125
 
            dbus_error_free(&err);
126
 
            free(servicename);
127
 
            free(dbusmodule);
128
 
            return NULL;
129
 
        }
130
 
        if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
131
 
            FcitxLog(WARNING, "DBus Service Already Exists");
132
 
            
133
 
            if (FcitxInstanceIsTryReplace(instance)) {
134
 
                FcitxInstanceResetTryReplace(instance);
135
 
                DBusMessage* message = dbus_message_new_method_call(servicename, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "Exit");
136
 
                dbus_connection_send(dbusmodule->conn, message, NULL);
137
 
                /* synchronize call here */
138
 
                DBusMessage* reply = dbus_connection_send_with_reply_and_block(dbusmodule->conn, message, 0, &err);
139
 
                
140
 
                if (dbus_error_is_set(&err)) {
141
 
                    dbus_error_free(&err);
142
 
                    dbus_error_init(&err);
143
 
                }
144
 
                
145
 
                if (reply)
146
 
                    dbus_message_unref(reply);
147
 
                dbus_message_unref(message);
148
 
                
149
 
                /* sleep for a while and retry */
150
 
                sleep(1);
151
 
                
152
 
                request_retry = true;
153
 
                continue;
154
 
            }
155
 
            
156
 
            dbus_error_free(&err);
157
 
            free(servicename);
158
 
            free(dbusmodule);
159
 
            return NULL;
160
 
        }
161
 
    } while (request_retry);
162
 
 
163
 
    free(servicename);
164
 
 
165
 
    dbus_connection_flush(conn);
166
 
    AddFunction(dbusaddon, DBusGetConnection);
167
 
    dbus_error_free(&err);
168
 
 
169
 
    return dbusmodule;
170
 
}
171
 
 
172
 
void* DBusGetConnection(void* arg, FcitxModuleFunctionArg args)
173
 
{
174
 
    FcitxDBus* dbusmodule = (FcitxDBus*)arg;
175
 
    return dbusmodule->conn;
176
 
}
177
 
 
178
 
static dbus_bool_t FcitxDBusAddWatch(DBusWatch *watch, void *data)
179
 
{
180
 
    FcitxDBusWatch *w;
181
 
    FcitxDBus* dbusmodule = (FcitxDBus*) data;
182
 
 
183
 
    for (w = dbusmodule->watches; w; w = w->next)
184
 
        if (w->watch == watch)
185
 
            return TRUE;
186
 
 
187
 
    if (!(w = fcitx_utils_malloc0(sizeof(FcitxDBusWatch))))
188
 
        return FALSE;
189
 
 
190
 
    w->watch = watch;
191
 
    w->next = dbusmodule->watches;
192
 
    dbusmodule->watches = w;
193
 
    return TRUE;
194
 
}
195
 
 
196
 
static void FcitxDBusRemoveWatch(DBusWatch *watch, void *data)
197
 
{
198
 
    FcitxDBusWatch **up, *w;
199
 
    FcitxDBus* dbusmodule = (FcitxDBus*) data;
200
 
 
201
 
    for (up = &(dbusmodule->watches), w = dbusmodule->watches; w; w = w->next) {
202
 
        if (w->watch == watch) {
203
 
            *up = w->next;
204
 
            free(w);
205
 
        } else
206
 
            up = &(w->next);
207
 
    }
208
 
}
209
 
 
210
 
void DBusSetFD(void* arg)
211
 
{
212
 
    FcitxDBus* dbusmodule = (FcitxDBus*) arg;
213
 
    FcitxDBusWatch *w;
214
 
    FcitxInstance* instance = dbusmodule->owner;
215
 
 
216
 
    for (w = dbusmodule->watches; w; w = w->next)
217
 
        if (dbus_watch_get_enabled(w->watch)) {
218
 
            unsigned int flags = dbus_watch_get_flags(w->watch);
219
 
            int fd = dbus_watch_get_unix_fd(w->watch);
220
 
 
221
 
            if (FcitxInstanceGetMaxFD(instance) < fd)
222
 
                FcitxInstanceSetMaxFD(instance, fd);
223
 
 
224
 
            if (flags & DBUS_WATCH_READABLE)
225
 
                FD_SET(fd, FcitxInstanceGetReadFDSet(instance));
226
 
 
227
 
            if (flags & DBUS_WATCH_WRITABLE)
228
 
                FD_SET(fd, FcitxInstanceGetWriteFDSet(instance));
229
 
 
230
 
            FD_SET(fd, FcitxInstanceGetExceptFDSet(instance));
231
 
        }
232
 
}
233
 
 
234
 
 
235
 
void DBusProcessEvent(void* arg)
236
 
{
237
 
    FcitxDBus* dbusmodule = (FcitxDBus*) arg;
238
 
    DBusConnection *connection = (DBusConnection *)dbusmodule->conn;
239
 
    FcitxInstance* instance = dbusmodule->owner;
240
 
    FcitxDBusWatch *w;
241
 
 
242
 
    for (w = dbusmodule->watches; w; w = w->next) {
243
 
        if (dbus_watch_get_enabled(w->watch)) {
244
 
            unsigned int flags = 0;
245
 
            int fd = dbus_watch_get_unix_fd(w->watch);
246
 
 
247
 
            if (FD_ISSET(fd, FcitxInstanceGetReadFDSet(instance)))
248
 
                flags |= DBUS_WATCH_READABLE;
249
 
 
250
 
            if (FD_ISSET(fd, FcitxInstanceGetWriteFDSet(instance)))
251
 
                flags |= DBUS_WATCH_WRITABLE;
252
 
 
253
 
            if (FD_ISSET(fd, FcitxInstanceGetExceptFDSet(instance)))
254
 
                flags |= DBUS_WATCH_ERROR;
255
 
 
256
 
            if (flags != 0)
257
 
                dbus_watch_handle(w->watch, flags);
258
 
        }
259
 
    }
260
 
 
261
 
    if (connection) {
262
 
        dbus_connection_ref(connection);
263
 
        while (dbus_connection_dispatch(connection) == DBUS_DISPATCH_DATA_REMAINS);
264
 
        dbus_connection_unref(connection);
265
 
    }
266
 
}
267
 
// kate: indent-mode cstyle; space-indent on; indent-width 0;