请问全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?
请问全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?
本回答来源全志R329如何解决调用Bluez mainloop_add_fd函数失败的问题?
可参考以下方法
问题背景
Tina系统使用的蓝牙协议栈为开源bluez协议栈,在上层应用开发的时候会常常使用mainloop_add_fd函数,尤其是btmanager中也有很多模块是调用了该函数。
问题描述
在使用Tina btmanager ble模块时,启动异常,提示打印"Failed to add listen socket(11),error(-38)",详细如下:
1607334876.975885: [gatt_run:355]: ++
1607334876.976066: [l2cap_le_att_listen:263]: ++
1607334876.976208: [l2cap_le_att_listen:296]: Started listening on ATT channel
1607334876.976311: [gatt_run:371]: sockfds 12 13
1607334876.976820: [gatt_set_bta_mainloop_id:27]: tid: 3047021836
1607334876.977276: [gatt_run:373]: tid 3047021836
1607334876.977541: [gatt_set_bta_cmd_fd:39]: gatt_commfds 12 13
1607334876.977884: [gatt_bta_register_handler:44]: ++
1607334876.979351: [gatt_run:383]: Failed to add listen socket(11),error(-38)
问题分析
"[gatt_run:383]: Failed to add listen socket(11),error(-38)"该行错误打印,提示的源代码如下:
ret = mainloop_add_fd(fd, EPOLLIN, server_listen_cb, server, NULL);
if (ret < 0) {
BTMG_ERROR("Failed to add listen socket(%d),error(%d)\n",fd,ret);
close(fd);
netcfg_state = 0;
return NULL;
}
从上可以判断是调用了mainloop_add_fd函数异常,该函数是链接的开源bluez协议栈中的库,于是搜索了bluez中关于mainloop_add_fd的实现,发现实现该函数有有三处地方,分别是
(1)src/shared/mainloop-ell.c:编入到src/.libs/libshared-ell.a库中。
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
return -ENOSYS;
}
(2)src/shared/mainloop-glib.c:编入到src/.libs/libshared-glib.a库中。
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
return -ENOSYS;
}
(3) src/shared/mainloop.c:编入到src/.libs/libshared-mainloop.a库中。
int mainloop_add_fd(int fd, uint32_t events, mainloop_event_func callback,
void *user_data, mainloop_destroy_func destroy)
{
struct mainloop_data *data;
struct epoll_event ev;
int err;
if (fd < 0 || fd > MAX_MAINLOOP_ENTRIES - 1 || !callback)
return -EINVAL;
data = malloc(sizeof(*data));
if (!data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
data->fd = fd;
data->events = events;
data->callback = callback;
data->destroy = destroy;
data->user_data = user_data;
memset(&ev, 0, sizeof(ev));
ev.events = events;
ev.data.ptr = data;
err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, data->fd, &ev);
if (err < 0) {
free(data);
return err;
}
mainloop_list[fd] = data;
return 0;
}
而 Failed to add listen socket(11),error(-38)提示-38正好是"-ENOSYS", 在errno.h中有定义
#define ENOSYS 38 /* Function not implemented */
所以排查到是链接的函数不对,应用程序中同时链接了libshared-glib.a和libshared-mainloop.a,最后取用的是libshared-glib.a,应该使用的是libshared-mainloop.a。
解决办法
在使用mainloop_add_fd函数的时候,要尤其注意,要链接使用正确的库。使用libshared-mainloop.a而不是libshared-glib.a和libshared-ell.a。