4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
11 * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12 * Nikita Kalyazin <n.kalyazin@samsung.com>
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
18 * http://www.apache.org/licenses/LICENSE-2.0
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
28 * - Samsung RnD Institute Russia
33 #include <stdlib.h> // for realpath
34 #include <string.h> // for strtok, strcpy, strncpy
35 #include <limits.h> // for realpath
37 #include <errno.h> // for errno
38 #include <sys/types.h> // for accept, mkdir, opendir, readdir
39 #include <sys/socket.h> // for accept
40 #include <sys/stat.h> // for mkdir
41 #include <sys/eventfd.h> // for eventfd
42 #include <sys/epoll.h> // for epoll apis
43 #include <sys/timerfd.h> // for timerfd
44 #include <unistd.h> // for access, sleep
49 #include <attr/xattr.h> // for fsetxattr
50 #include <sys/smack.h>
53 #include <linux/input.h>
59 #include "da_protocol.h"
62 #include "process_info.h"
64 #define DA_WORK_DIR "/home/developer/sdk_tools/da/"
65 #define DA_READELF_PATH "/home/developer/sdk_tools/da/readelf"
66 #define SCREENSHOT_DIR "/tmp/da"
69 #define MAX_CONNECT_SIZE 12
70 #define MAX_APP_LAUNCH_TIME 6
73 #define MAX_FILENAME 128
75 #define ARRAY_END (-11)
77 input_dev g_key_dev[MAX_DEVICE];
78 input_dev g_touch_dev[MAX_DEVICE];
80 // return bytes size of readed data
81 // return 0 if no data readed or error occurred
82 static int _file_read(FILE* fp, char *buffer, int size)
86 if(fp != NULL && size > 0)
88 ret = fread((void*)buffer, sizeof(char), size, fp);
96 ret = 0; // error case
102 // get input id of given input device
103 static int get_input_id(char* inputname)
105 static int query_cmd_type = 0; // 1 if /lib/udev/input_id, 2 if udevadm
107 char buffer[BUF_SIZE];
108 char command[MAX_FILENAME];
111 // determine input_id query command
112 if(unlikely(query_cmd_type == 0))
114 if(access("/lib/udev/input_id", F_OK) == 0) // there is /lib/udev/input_id
118 else // there is not /lib/udev/input_id
124 // make command string
125 if(query_cmd_type == 1)
127 sprintf(command, "/lib/udev/input_id /class/input/%s", inputname);
131 sprintf(command, "udevadm info --name=input/%s --query=property", inputname);
135 cmd_fp = popen(command, "r");
136 _file_read(cmd_fp, buffer, BUF_SIZE);
138 // determine input id
139 if(strstr(buffer, INPUT_ID_STR_KEY)) // key
143 else if(strstr(buffer, INPUT_ID_STR_TOUCH)) // touch
145 ret = INPUT_ID_TOUCH;
147 else if(strstr(buffer, INPUT_ID_STR_KEYBOARD)) // keyboard
151 else if(strstr(buffer, INPUT_ID_STR_TABLET)) // touch (emulator)
153 ret = INPUT_ID_TOUCH;
161 // get filename and fd of given input type devices
162 static void _get_fds(input_dev *dev, int input_id)
168 dp = opendir("/sys/class/input");
172 while((d = readdir(dp)) != NULL)
174 if(!strncmp(d->d_name, "event", 5)) // start with "event"
177 if(input_id == get_input_id(d->d_name))
179 sprintf(dev[count].fileName, "/dev/input/%s", d->d_name);
180 dev[count].fd = open(dev[count].fileName, O_RDWR | O_NONBLOCK);
188 dev[count].fd = ARRAY_END; // end of input_dev array
192 void _device_write(input_dev *dev, struct input_event* in_ev)
195 for(i = 0; dev[i].fd != ARRAY_END; i++)
199 write(dev[i].fd, in_ev, sizeof(struct input_event));
200 LOGI("write(%d, %d, %d)\n",
201 dev[i].fd, (int)in_ev, sizeof(struct input_event));
206 long long get_total_alloc_size()
209 long long allocsize = 0;
211 for(i = 0; i < MAX_TARGET_COUNT; i++)
213 if(manager.target[i].socket != -1 && manager.target[i].allocmem > 0)
214 allocsize += manager.target[i].allocmem;
219 static int getEmptyTargetSlot()
222 for(i = 0; i < MAX_TARGET_COUNT; i++)
224 if(manager.target[i].socket == -1)
231 static void setEmptyTargetSlot(int index)
233 if(index >= 0 && index < MAX_TARGET_COUNT)
235 manager.target[index].pid = -1;
236 manager.target[index].recv_thread = -1;
237 manager.target[index].allocmem = 0;
238 manager.target[index].starttime = 0;
239 manager.target[index].initial_log = 0;
240 if(manager.target[index].event_fd != -1)
241 close(manager.target[index].event_fd);
242 manager.target[index].event_fd = -1;
243 if(manager.target[index].socket != -1)
244 close(manager.target[index].socket);
245 manager.target[index].socket = -1;
249 // =============================================================================
250 // send functions to host
251 // =============================================================================
254 int sendACKCodeToHost(enum HostMessageType resp, int msgcode)
257 //disabled string protocol
259 if (manager.host.control_socket != -1)
262 char logstr[DA_MSG_MAX];
265 codelen = sprintf(codestr, "%d", msgcode);
266 loglen = sprintf(logstr, "%d|%d|%s", (int)resp, codelen, codestr);
268 send(manager.host.control_socket, logstr, loglen, MSG_NOSIGNAL);
275 // =============================================================================
276 // start and terminate control functions
277 // =============================================================================
279 static int exec_app(const struct app_info_t *app_info)
282 static struct epoll_event ev;
285 switch (app_info->app_type) {
287 kill_app(app_info->exe_path);
288 if (exec_app_tizen(app_info->app_id, app_info->exe_path)) {
289 LOGE("Cannot exec tizen app %s\n", app_info->app_id);
293 case APP_TYPE_RUNNING:
294 // TODO: nothing, it's running
295 LOGI("already started\n");
296 write_process_info(atoi(app_info->app_id), 0);
298 case APP_TYPE_COMMON:
299 kill_app(app_info->exe_path);
300 if (exec_app_common(app_info->exe_path)) {
301 LOGE("Cannot exec common app %s\n", app_info->exe_path);
306 LOGE("Unknown app type %d\n", app_info->app_type);
311 if (res == 0 && app_info->app_type != APP_TYPE_RUNNING) {
312 manager.app_launch_timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
313 if(manager.app_launch_timerfd > 0)
315 struct itimerspec ctime;
316 ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME;
317 ctime.it_value.tv_nsec = 0;
318 ctime.it_interval.tv_sec = 0;
319 ctime.it_interval.tv_nsec = 0;
320 if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0)
322 LOGE("fail to set app launch timer\n");
323 close(manager.app_launch_timerfd);
324 manager.app_launch_timerfd = -1;
328 // add event fd to epoll list
330 ev.data.fd = manager.app_launch_timerfd;
331 if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
332 manager.app_launch_timerfd, &ev) < 0)
334 // fail to add event fd
335 LOGE("fail to add app launch timer fd to epoll list\n");
336 close(manager.app_launch_timerfd);
337 manager.app_launch_timerfd = -1;
339 LOGI("application launch time started\n");
343 LOGE("cannot create launch timer\n");
347 LOGI("ret=%d\n", res);
351 static void epoll_add_input_events();
352 static void epoll_del_input_events();
354 int start_profiling()
356 const struct app_info_t *app_info = &prof_session.app_info;
359 // remove previous screen capture files
360 remove_indir(SCREENSHOT_DIR);
361 mkdir(SCREENSHOT_DIR, 0777);
363 smack_lsetlabel(SCREENSHOT_DIR, "*", SMACK_LABEL_ACCESS);
366 if (IS_OPT_SET(FL_CPU | FL_MEMORY)) {
367 if (samplingStart() < 0) {
368 LOGE("Cannot start sampling\n");
374 if (IS_OPT_SET(FL_RECORDING))
375 epoll_add_input_events();
377 if (exec_app(app_info)) {
378 LOGE("Cannot exec app\n");
386 if (IS_OPT_SET(FL_RECORDING))
387 epoll_del_input_events();
388 if (IS_OPT_SET(FL_CPU | FL_MEMORY))
392 LOGI("return %d\n", res);
396 void stop_profiling(void)
398 if (IS_OPT_SET(FL_RECORDING))
399 epoll_del_input_events();
400 if (IS_OPT_SET(FL_CPU | FL_MEMORY))
404 static void reconfigure_recording(struct conf_t conf)
406 uint64_t old_features = prof_session.conf.use_features0;
407 uint64_t new_features = conf.use_features0;
408 uint64_t to_enable = (new_features ^ old_features) & new_features;
409 uint64_t to_disable = (new_features ^ old_features) & old_features;
411 if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
412 epoll_del_input_events();
413 prof_session.conf.use_features0 &= ~FL_RECORDING;
416 if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
417 epoll_add_input_events();
418 prof_session.conf.use_features0 |= FL_RECORDING;
423 static int reconfigure_cpu_and_memory(struct conf_t conf)
425 uint64_t old_features = prof_session.conf.use_features0;
426 uint64_t new_features = conf.use_features0;
427 uint64_t to_enable = (new_features ^ old_features) & new_features;
428 uint64_t to_disable = (new_features ^ old_features) & old_features;
430 prof_session.conf.system_trace_period = conf.system_trace_period;
432 if (IS_OPT_SET(FL_CPU | FL_MEMORY))
435 if (IS_OPT_SET_IN(FL_CPU | FL_MEMORY, to_disable)) {
436 prof_session.conf.use_features0 &= ~(FL_CPU | FL_MEMORY);
440 if (IS_OPT_SET_IN(FL_CPU | FL_MEMORY, to_enable)) {
441 if (samplingStart() < 0) {
442 LOGE("Cannot start sampling\n");
445 prof_session.conf.use_features0 |= (FL_CPU | FL_MEMORY);
451 int reconfigure(struct conf_t conf)
453 reconfigure_recording(conf);
454 if (reconfigure_cpu_and_memory(conf)) {
455 LOGE("Cannot reconf cpu and memory\n");
462 // just send stop message to all target process
463 static void terminate_all_target()
467 msg_target_t sendlog;
469 sendlog.type = MSG_STOP;
472 for (i = 0; i < MAX_TARGET_COUNT; i++)
474 if(manager.target[i].socket != -1)
476 sendlen = send(manager.target[i].socket, &sendlog,
477 sizeof(sendlog.type) + sizeof(sendlog.length),
481 LOGI("TERMINATE send exit msg (socket %d) "
482 "by terminate_all_target()\n", manager.target[i].socket);
488 // terminate all target and wait for threads
492 terminate_all_target();
494 // wait for all other thread exit
495 for(i = 0; i < MAX_TARGET_COUNT; i++)
497 if(manager.target[i].recv_thread != -1)
499 pthread_join(manager.target[i].recv_thread, NULL);
504 // terminate all profiling by critical error
505 // TODO: don't send data to host
506 static void terminate_error(char* errstr, int send_to_host)
508 LOGE("termination all with err '%s'\n", errstr);
509 struct msg_data_t *msg = NULL;
510 if (send_to_host != 0){
511 msg = gen_message_error(errstr);
516 LOGI("cannot generate error message\n");
522 #define MAX_EVENTS_NUM 10
523 static int deviceEventHandler(input_dev* dev, int input_type)
528 struct input_event in_ev[MAX_EVENTS_NUM];
529 struct msg_data_t *log;
531 if(input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY)
534 size = read(dev->fd, &in_ev[count], sizeof(*in_ev) );
537 } while (count < MAX_EVENTS_NUM && size > 0);
540 LOGI("read %d %s events\n",
542 input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
543 log = gen_message_event(in_ev, count, input_type);
544 printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
551 LOGW("unknown input_type\n");
557 // return 0 if normal case
558 // return plus value if non critical error occur
559 // return minus value if critical error occur
560 // return -11 if all target process closed
561 static int targetEventHandler(int epollfd, int index, uint64_t msg)
565 if (index == 0) { // main application
567 if ( is_same_app_process(prof_session.app_info.exe_path,
568 manager.target[index].pid) == 0 ) {
569 LOGE("is same error: '%s' is not %d\n",
570 prof_session.app_info.exe_path,
571 manager.target[index].pid);
575 if (start_replay() != 0) {
576 LOGE("Cannot start replay thread\n");
580 manager.target[index].initial_log = 1;
583 if(msg & EVENT_STOP || msg & EVENT_ERROR)
585 LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
586 manager.target[index].socket,
587 manager.target[index].pid,
588 manager.target_count - 1);
589 if (index == 0) { // main application
592 epoll_ctl(epollfd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
593 setEmptyTargetSlot(index);
594 // all target client are closed
595 if (0 == __sync_sub_and_fetch(&manager.target_count, 1))
602 // return 0 if normal case
603 // return plus value if non critical error occur
604 // return minus value if critical error occur
605 static int targetServerHandler(int efd)
608 struct epoll_event ev;
610 int index = getEmptyTargetSlot();
611 if(index == MAX_TARGET_COUNT)
613 LOGW("Max target number(8) reached, no more target can connected\n");
617 manager.target[index].socket =
618 accept(manager.target_server_socket, NULL, NULL);
620 if(manager.target[index].socket >= 0) // accept succeed
623 // set smack attribute for certification
624 fsetxattr(manager.target[index].socket, "security.SMACK64IPIN", "*", 1, 0);
625 fsetxattr(manager.target[index].socket, "security.SMACK64IPOUT", "*", 1, 0);
626 #endif /* LOCALTEST */
628 // send config message to target process
629 log.type = MSG_OPTION;
630 log.length = sprintf(log.data, "%u",
631 prof_session.conf.use_features0);
632 send(manager.target[index].socket, &log,
633 sizeof(log.type) + sizeof(log.length) + log.length,
637 manager.target[index].event_fd = eventfd(0, EFD_NONBLOCK);
638 if(manager.target[index].event_fd == -1)
640 // fail to make event fd
641 LOGE("fail to make event fd for socket (%d)\n",
642 manager.target[index].socket);
643 goto TARGET_CONNECT_FAIL;
646 // add event fd to epoll list
648 ev.data.fd = manager.target[index].event_fd;
649 if(epoll_ctl(efd, EPOLL_CTL_ADD, manager.target[index].event_fd, &ev) < 0)
651 // fail to add event fd
652 LOGE("fail to add event fd to epoll list for socket (%d)\n",
653 manager.target[index].socket);
654 goto TARGET_CONNECT_FAIL;
657 // make recv thread for target
658 if(makeRecvThread(index) != 0)
660 // fail to make recv thread
661 LOGE("fail to make recv thread for socket (%d)\n",
662 manager.target[index].socket);
663 epoll_ctl(efd, EPOLL_CTL_DEL, manager.target[index].event_fd, NULL);
664 goto TARGET_CONNECT_FAIL;
667 if(manager.app_launch_timerfd >= 0)
669 LOGI("release launch timer\n");
670 epoll_ctl(efd, EPOLL_CTL_DEL, manager.app_launch_timerfd, NULL);
671 close(manager.app_launch_timerfd);
672 manager.app_launch_timerfd = -1;
675 LOGI("target connected = %d(running %d target)\n",
676 manager.target[index].socket, manager.target_count + 1);
678 manager.target_count++;
683 LOGE("Failed to accept at target server socket\n");
687 if(manager.target_count == 0) // if this connection is main connection
693 // if this connection is not main connection then ignore process by error
694 setEmptyTargetSlot(index);
699 // return 0 if normal case
700 // return plus value if non critical error occur
701 // return minus value if critical error occur
702 static int hostServerHandler(int efd)
704 static int hostserverorder = 0;
706 struct epoll_event ev;
708 if(hostserverorder > 1) // control and data socket connected already
711 csocket = accept(manager.host_server_socket, NULL, NULL);
713 if(csocket >= 0) // accept succeed
716 ev.data.fd = csocket;
717 if(epoll_ctl(efd, EPOLL_CTL_ADD, csocket, &ev) < 0)
719 // consider as accept fail
720 LOGE("Failed to add socket fd to epoll list\n");
725 if(hostserverorder == 0)
727 manager.host.control_socket = csocket;
729 LOGI("host control socket connected = %d\n", csocket);
733 manager.host.data_socket = csocket;
734 LOGI("host data socket connected = %d\n", csocket);
742 LOGE("Failed to accept from host server socket\n");
748 // return 0 if normal case
749 // return plus value if non critical error occur
750 // return minus value if critical error occur
751 // return -11 if socket closed
753 static int controlSocketHandler(int efd)
756 struct msg_t msg_head;
761 recv_len = recv(manager.host.control_socket,
764 // error or close request from host
765 if (recv_len == -1 || recv_len == 0)
768 msg = malloc(MSG_CMD_HDR_LEN + msg_head.len);
770 LOGE("Cannot alloc msg\n");
771 sendACKCodeToHost(MSG_NOTOK, ERR_WRONG_MESSAGE_FORMAT);
774 msg->id = msg_head.id;
775 msg->len = msg_head.len;
777 // Receive payload (if exists)
778 recv_len = recv(manager.host.control_socket,
780 msg->len, MSG_WAITALL);
784 res = host_message_handler(msg);
791 static void epoll_add_input_events()
793 struct epoll_event ev;
796 // add device fds to epoll event pool
798 for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
799 if (g_key_dev[i].fd >= 0) {
800 ev.data.fd = g_key_dev[i].fd;
801 if (epoll_ctl(manager.efd,
803 g_key_dev[i].fd, &ev) < 0)
804 LOGE("keyboard device file epoll_ctl error\n");
809 for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
810 if (g_touch_dev[i].fd >= 0) {
811 ev.data.fd = g_touch_dev[i].fd;
812 if (epoll_ctl(manager.efd,
814 g_touch_dev[i].fd, &ev) < 0)
815 LOGE("touch device file epoll_ctl error\n");
820 static void epoll_del_input_events()
824 // remove device fds from epoll event pool
825 for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
826 if (g_key_dev[i].fd >= 0)
827 if (epoll_ctl(manager.efd,
829 g_key_dev[i].fd, NULL) < 0)
830 LOGE("keyboard device file epoll_ctl error\n");
832 for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
833 if (g_touch_dev[i].fd >= 0)
834 if (epoll_ctl(manager.efd,
836 g_touch_dev[i].fd, NULL) < 0)
837 LOGE("touch device file epoll_ctl error\n");
840 // return 0 for normal case
843 int ret = 0; // return value
847 struct epoll_event ev, *events;
848 int numevent; // number of occured events
850 _get_fds(g_key_dev, INPUT_ID_KEY);
851 _get_fds(g_touch_dev, INPUT_ID_TOUCH);
853 // initialize epoll event pool
854 events = (struct epoll_event*) malloc(sizeof(struct epoll_event) * EPOLL_SIZE);
857 LOGE("Out of memory when allocate epoll event pool\n");
861 if((manager.efd = epoll_create(MAX_CONNECT_SIZE)) < 0)
863 LOGE("epoll creation error\n");
868 // add server sockets to epoll event pool
870 ev.data.fd = manager.host_server_socket;
871 if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
872 manager.host_server_socket, &ev) < 0)
874 LOGE("Host server socket epoll_ctl error\n");
879 ev.data.fd = manager.target_server_socket;
880 if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
881 manager.target_server_socket, &ev) < 0)
883 LOGE("Target server socket epoll_ctl error\n");
891 numevent = epoll_wait(manager.efd, events, EPOLL_SIZE, -1);
894 LOGE("Failed to epoll_wait : "
895 "num of event(%d), errno(%d)\n", numevent, errno);
899 for(i = 0; i < numevent; i++)
901 // check for request from event fd
902 for(k = 0; k < MAX_TARGET_COUNT; k++)
904 if(manager.target[k].socket != -1 &&
905 events[i].data.fd == manager.target[k].event_fd)
908 recvLen = read(manager.target[k].event_fd, &u, sizeof(uint64_t));
909 if(recvLen != sizeof(uint64_t))
911 // maybe closed, but ignoring is more safe then
912 // removing fd from epoll list
916 if(-11 == targetEventHandler(manager.efd, k, u))
918 LOGI("all target process is closed\n");
926 if(k != MAX_TARGET_COUNT)
929 // check for request from device fd
930 for(k = 0; g_touch_dev[k].fd != ARRAY_END; k++)
932 if(g_touch_dev[k].fd >= 0 &&
933 events[i].data.fd == g_touch_dev[k].fd)
935 if(deviceEventHandler(&g_touch_dev[k], INPUT_ID_TOUCH) < 0)
937 terminate_error("Internal DA framework error, "
938 "Please re-run the profiling.", 1);
946 if(g_touch_dev[k].fd != ARRAY_END)
949 for(k = 0; g_key_dev[k].fd != ARRAY_END; k++)
951 if(g_key_dev[k].fd >= 0 &&
952 events[i].data.fd == g_key_dev[k].fd)
954 if(deviceEventHandler(&g_key_dev[k], INPUT_ID_KEY) < 0)
956 terminate_error("Internal DA framework error, "
957 "Please re-run the profiling.", 1);
965 if(g_key_dev[k].fd != ARRAY_END)
968 // connect request from target
969 if(events[i].data.fd == manager.target_server_socket)
971 if(targetServerHandler(manager.efd) < 0) // critical error
973 terminate_error("Internal DA framework error, "
974 "Please re-run the profiling.", 1);
979 // connect request from host
980 else if(events[i].data.fd == manager.host_server_socket)
982 int result = hostServerHandler(manager.efd);
985 terminate_error("Internal DA framework error, "
986 "Please re-run the profiling.", 1);
991 // control message from host
992 else if(events[i].data.fd == manager.host.control_socket)
994 int result = controlSocketHandler(manager.efd);
995 if(result == -11) // socket close
997 // close target and host socket and quit
998 LOGI("host close = %d\n", manager.host.control_socket);
1004 terminate_error("Internal DA framework error, "
1005 "Please re-run the profiling.", 1);
1010 else if(events[i].data.fd == manager.host.data_socket)
1013 recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
1015 { // close data socket
1016 epoll_ctl(manager.efd, EPOLL_CTL_DEL,
1017 manager.host.data_socket,
1019 close(manager.host.data_socket);
1020 manager.host.data_socket = -1;
1021 // TODO: finish transfer thread
1024 LOGI("host message from data socket %d\n", recvLen);
1026 // check for application launch timerfd
1027 else if(events[i].data.fd == manager.app_launch_timerfd)
1029 // send to host timeout error message for launching application
1030 terminate_error("Failed to launch application", 1);
1031 epoll_ctl(manager.efd, EPOLL_CTL_DEL,
1032 manager.app_launch_timerfd, NULL);
1033 close(manager.app_launch_timerfd);
1034 manager.app_launch_timerfd = -1;
1042 LOGW("Unknown socket fd (%d)\n", events[i].data.fd);
1048 LOGI("close efd\n");