fds[0].events = POLLOUT;
fds[0].revents = 0;
- do {
- r = poll(fds, 1, SEND_TIMEOUT);
- if (r == -1) {
- if (errno == EINTR)
- continue;
-
- bxt_err("send: fd %d poll errno %d", fd, errno);
- free(buf);
-
- return -1;
- }
-
- if (r == 0) {
- bxt_err("send: fd %d poll timeout", fd);
- free(buf);
- errno = ETIMEDOUT;
-
- return -1;
- }
- } while (r < 0);
+ if (type != MSG_NOTI) {
+ do {
+ r = poll(fds, 1, SEND_TIMEOUT);
+ if (r == -1) {
+ if (errno == EINTR)
+ continue;
+
+ bxt_err("send: fd %d poll errno %d", fd, errno);
+ free(buf);
+
+ return -1;
+ }
+
+ if (r == 0) {
+ bxt_err("send: fd %d poll timeout", fd);
+ free(buf);
+ errno = ETIMEDOUT;
+
+ return -1;
+ }
+ } while (r < 0);
+ }
r = send(fd, buf, sizeof(*hdr) + len, MSG_NOSIGNAL);
return get_search_key(layer, key, u);
}
+static gboolean _send_notis(gpointer key, gpointer value, gpointer data)
+{
+ int r;
+ guchar *_data;
+ gsize _len;
+ struct bxt_client *cli = (struct bxt_client *)data;
+ gchar *g_data = (gchar *)value;
+
+ _data = g_base64_decode(g_data, &_len);
+
+ r = proto_send(cli->fd, MSG_NOTI, (uint8_t *)_data, (int)_len);
+ if (r == -1) {
+ bxt_err("send noti again key : %s pid : %d errno : %d",
+ key, cli->cred.pid, errno);
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ free(_data);
+ return FALSE;
+ }
+ }
+
+ free(_data);
+ return TRUE;
+}
+
+static gboolean _send_delayed_noti(gint fd, GIOCondition cond, gpointer data)
+{
+ struct bxt_client *cli = (struct bxt_client *)data;
+
+ if (cli->delay_notilist && g_hash_table_size(cli->delay_notilist) > 0)
+ g_hash_table_foreach_remove(cli->delay_notilist,
+ (GHRFunc)_send_notis, cli);
+
+ if (g_hash_table_size(cli->delay_notilist) > 0)
+ return G_SOURCE_CONTINUE;
+
+ cli->fd_out_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
static void send_notis(struct bxt_daemon *bxtd, struct request *rqst)
{
int r;
struct request req;
uint8_t *data;
int len;
+ gchar *_data;
assert(bxtd);
assert(rqst);
struct bxt_client *cli = l->data;
r = proto_send(cli->fd, req.type, data, len);
- if (r == -1)
- bxt_err("send notis: cli %p error %d", cli, errno);
+ if (r == -1) {
+ bxt_err("send notis: cli pid : %d label : %s key : %s error %d",
+ cli->cred.pid, cli->label, rqst->key, errno);
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ _data = g_base64_encode(data, len);
+
+ if (cli->fd_out_id == 0) {
+ cli->fd_out_id = g_unix_fd_add_full(G_PRIORITY_DEFAULT,
+ cli->fd, G_IO_OUT, _send_delayed_noti,
+ cli, NULL);
+ }
+ if (!cli->delay_notilist) {
+ cli->delay_notilist = g_hash_table_new_full(g_str_hash,
+ g_str_equal,
+ (GDestroyNotify)free,
+ (GDestroyNotify)g_free);
+ }
+
+ g_hash_table_replace(cli->delay_notilist,
+ strdup(rqst->key), _data);
+ }
+ } else {
+ if (cli->delay_notilist)
+ g_hash_table_remove(cli->delay_notilist, rqst->key);
+ }
}
free(data);
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
client_cb, cli);
+ cli->fd_out_id = 0;
+
g_hash_table_insert(bxtd->clients, cli, cli);
bxt_dbg("Client %p added, fd %d", cli, fd);
}
g_list_free(cli->notilist);
cli->notilist = NULL;
+ if (cli->delay_notilist)
+ g_hash_table_destroy(cli->delay_notilist);
+
if (cli->fd_id)
g_source_remove(cli->fd_id);
+ if (cli->fd_out_id)
+ g_source_remove(cli->fd_out_id);
+
if (cli->fd != -1)
close(cli->fd);