From 73180fc762f015935950f697822710af3f5bd23d Mon Sep 17 00:00:00 2001 From: ManikandanC Date: Fri, 6 Oct 2017 11:37:31 +0530 Subject: Use poll in the dlt-daemon for POSIX compliance The poll system call is now used in the daemon to enable DLT use in POSIX compliant systems. Also added introduced new unregister_app macro to avoid missing of logs in startup buffer. Signed-off-by: Frederic Berat Signed-off-by: ManikandanC Signed-off-by: Saya Sugiura Signed-off-by: S. Hameed --- src/adaptor/dlt-adaptor-stdin.c | 19 +- src/console/dlt-receive.c | 21 ++- src/console/logstorage/CMakeLists.txt | 30 ++-- src/console/logstorage/dlt-logstorage-ctrl.c | 168 +++++++++--------- src/console/logstorage/dlt-logstorage-list.c | 17 +- src/daemon/CMakeLists.txt | 19 +- src/daemon/dlt-daemon.c | 20 +-- src/daemon/dlt_daemon_connection.c | 6 +- src/daemon/dlt_daemon_connection_types.h | 4 +- src/daemon/dlt_daemon_event_handler.c | 254 +++++++++++++++++---------- src/daemon/dlt_daemon_event_handler.h | 2 +- src/daemon/dlt_daemon_event_handler_types.h | 8 +- src/gateway/dlt_gateway.c | 12 +- src/gateway/dlt_gateway.h | 2 +- src/lib/CMakeLists.txt | 17 +- src/lib/dlt_user.c | 46 ++++- src/shared/dlt_common.c | 2 + src/tests/dlt-test-multi-process.c | 4 + 18 files changed, 416 insertions(+), 235 deletions(-) (limited to 'src') diff --git a/src/adaptor/dlt-adaptor-stdin.c b/src/adaptor/dlt-adaptor-stdin.c index eae7000..aeca49b 100644 --- a/src/adaptor/dlt-adaptor-stdin.c +++ b/src/adaptor/dlt-adaptor-stdin.c @@ -92,11 +92,12 @@ int main(int argc, char* argv[]) char version[255]; int timeout = -1; int verbosity = DLT_LOG_INFO; + int bflag = 0; dlt_set_id(apid, PS_DLT_APP); dlt_set_id(ctid, PS_DLT_CONTEXT); - while ((opt = getopt(argc, argv, "a:c:ht:v:")) != -1) + while ((opt = getopt(argc, argv, "a:c:bht:v:")) != -1) { switch (opt) { @@ -110,6 +111,11 @@ int main(int argc, char* argv[]) dlt_set_id(ctid,optarg); break; } + case 'b': + { + bflag = 1; + break; + } case 't': { timeout = atoi(optarg); @@ -125,6 +131,7 @@ int main(int argc, char* argv[]) printf("Options:\n"); printf(" -a apid - Set application id to apid (default: SINA)\n"); printf(" -c ctid - Set context id to ctid (default: SINC)\n"); + printf(" -b - Flush buffered logs before unregistering app\n"); printf(" -t timeout - Set timeout when sending messages at exit, in ms (Default: 10000 = 10sec)\n"); printf(" -v verbosity level - Set verbosity level (Default: INFO, values: FATAL ERROR WARN INFO DEBUG VERBOSE)\n"); printf(" -h - This help\n"); @@ -194,7 +201,15 @@ int main(int argc, char* argv[]) } DLT_UNREGISTER_CONTEXT(mycontext); - DLT_UNREGISTER_APP(); + + if (bflag == 1) + { + DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS(); + } + else + { + DLT_UNREGISTER_APP(); + } return 0; } diff --git a/src/console/dlt-receive.c b/src/console/dlt-receive.c index 200add1..e22d15e 100644 --- a/src/console/dlt-receive.c +++ b/src/console/dlt-receive.c @@ -77,7 +77,11 @@ #include #include #include -#include /* for PATH_MAX */ +#ifdef __linux__ +#include +#else +#include +#endif #include #include "dlt_client.h" @@ -211,7 +215,7 @@ int dlt_receive_open_output_file(DltReceiveData * dltdata) { /* if (file_already_exists) */ glob_t outer; - if (glob(dltdata->ovalue, GLOB_TILDE_CHECK | GLOB_NOSORT, NULL, &outer) == 0) + if (glob(dltdata->ovalue, GLOB_TILDE | GLOB_NOSORT, NULL, &outer) == 0) { if (dltdata->vflag) { @@ -234,7 +238,7 @@ int dlt_receive_open_output_file(DltReceiveData * dltdata) * foo.1000.dlt * foo.11.dlt */ - if (glob(pattern, GLOB_TILDE_CHECK | GLOB_NOSORT, NULL, &inner) == 0) + if (glob(pattern, GLOB_TILDE | GLOB_NOSORT, NULL, &inner) == 0) { /* search for the highest number used */ size_t i; @@ -376,7 +380,16 @@ int main(int argc, char* argv[]) to_copy = to_copy - 4; } - dltdata.ovaluebase = strndup(dltdata.ovalue, to_copy); + dltdata.ovaluebase = (char *)calloc(1, to_copy + 1); + + if (dltdata.ovaluebase == NULL) + { + fprintf (stderr, "Memory allocation failed.\n"); + return -1; + } + + dltdata.ovaluebase[to_copy] = '\0'; + memcpy(dltdata.ovaluebase, dltdata.ovalue, to_copy); break; } case 'e': diff --git a/src/console/logstorage/CMakeLists.txt b/src/console/logstorage/CMakeLists.txt index 830bf5a..160d905 100644 --- a/src/console/logstorage/CMakeLists.txt +++ b/src/console/logstorage/CMakeLists.txt @@ -16,24 +16,26 @@ ####### add_definitions( -Werror ) -if(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP) - set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-udev.c dlt-logstorage-list.c) -elseif(WITH_DLT_LOGSTORAGE_CTRL_PROP) - set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-list.c) -elseif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) - set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-udev.c dlt-logstorage-list.c) -else(WITH_DLT_LOGSTORAGE_CTRL_UDEV) - set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-list.c) -endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP) - -add_executable(dlt-logstorage-ctrl ${dlt_logstorage_ctrl_SRCS} ${dlt_control_common_SRCS} ${dlt_most_SRCS} ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c ) +set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-list.c) if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) - target_link_libraries(dlt-logstorage-ctrl dlt udev ${EXPAT_LIBRARIES}) -else(WITH_DLT_LOGSTORAGE_CTRL_UDEV) - target_link_libraries(dlt-logstorage-ctrl dlt ${EXPAT_LIBRARIES}) + set(dlt_logstorage_ctrl_SRCS ${dlt_logstorage_ctrl_SRCS} dlt-logstorage-udev.c) endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) +if(WITH_SYSTEMD) + set(dlt_logstorage_ctrl_SRCS ${dlt_logstorage_ctrl_SRCS} ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c) +endif(WITH_SYSTEMD) + +add_executable(dlt-logstorage-ctrl ${dlt_logstorage_ctrl_SRCS} ${dlt_control_common_SRCS} ${dlt_most_SRCS}) + +set(DLT_LOGSTORAGE_LIBRARIES dlt-logstorage-ctrl dlt ${EXPAT_LIBRARIES}) + +if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + set(DLT_LOGSTORAGE_LIBRARIES ${DLT_LOGSTORAGE_LIBRARIES} udev) +endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + +target_link_libraries(${DLT_LOGSTORAGE_LIBRARIES}) + set_target_properties(dlt-logstorage-ctrl PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-logstorage-ctrl diff --git a/src/console/logstorage/dlt-logstorage-ctrl.c b/src/console/logstorage/dlt-logstorage-ctrl.c index 15ccc04..87e303b 100644 --- a/src/console/logstorage/dlt-logstorage-ctrl.c +++ b/src/console/logstorage/dlt-logstorage-ctrl.c @@ -63,9 +63,11 @@ #include #include -#include +#include +#if defined(__linux__) #include "sd-daemon.h" +#endif #include "dlt_protocol.h" #include "dlt_client.h" @@ -73,16 +75,19 @@ #include "dlt-logstorage-common.h" #include "dlt-logstorage-ctrl.h" -#define EPOLL_MAX_EVENTS 10 -#define EPOLL_TIME_OUT 500 +#define POLL_TIME_OUT 500 +#define EV_MASK_REJECTED (POLLERR | POLLHUP | POLLNVAL) #define DLT_LOGSTORAGE_CTRL_EXIT 1 static int must_exit; -static int efd; +struct dlt_event { + struct pollfd pfd; + void *func; +}; /** @brief Triggers the application exit * - * The application will exit on next epoll timeout. + * The application will exit on next poll timeout. */ void dlt_logstorage_exit(void) { @@ -91,7 +96,7 @@ void dlt_logstorage_exit(void) /** @brief Check if the application must exit * - * The application will exit on next epoll timeout. + * The application will exit on next poll timeout. */ int dlt_logstorage_must_exit(void) { @@ -203,22 +208,22 @@ static int analyze_response(char *data, void *payload, int len) return ret; } -/** @brief Add a new event to watch to the epoll instance +/** @brief Add a new event to watch * * This function could be exported to be used by udev/prop so that they can * register several events. - * There is no remove function as the removal is done on efd closure. * + * @param ev_hdl The structure containing the file descriptors * @param fd The file descriptor to watch * @param cb The callback to be called on event. * - * @return epoll_ctrl return value, or -1 on earlier failure. + * @return 0 on success, -1 if the parameters are invalid. */ -static int dlt_logstorage_ctrl_add_event(int fd, void *cb) +static int dlt_logstorage_ctrl_add_event(struct dlt_event *ev_hdl, + int fd, + void *cb) { - struct epoll_event event; - - if ((fd < 0) || !cb) + if ((fd < 0) || !cb || !ev_hdl) { pr_error("Wrong parameter to add event (%d %p)\n", fd, cb); return -1; @@ -226,96 +231,82 @@ static int dlt_logstorage_ctrl_add_event(int fd, void *cb) pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb); - event.data.ptr = cb; - event.events = EPOLLIN | EPOLLET; + ev_hdl->func = cb; + ev_hdl->pfd.fd = fd; - return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); + return 0; } /** @brief Main execution loop * - * Waits on events from the epoll fd, and executes the callbacks retrieved + * Waits on events, and executes the callbacks retrieved * back from the event structure. * * @return 0 on success, -1 otherwise. */ -static int dlt_logstorage_ctrl_execute_event_loop(int efd) +static int dlt_logstorage_ctrl_execute_event_loop(struct dlt_event *ev) { - struct epoll_event *events; - int i; int ret = 0; - int n = 0; + int (*callback)() = ev->func; - events = calloc(10, sizeof(struct epoll_event)); + ret = poll(&ev->pfd, 1, POLL_TIME_OUT); - if (!events) + if (ret <= 0) { - pr_error("No memory available for events.\n"); - return -1; - } - - n = epoll_wait(efd, events, EPOLL_MAX_EVENTS, EPOLL_TIME_OUT); - - if (n < 0) - { - pr_error("epoll_wait error: %s\n", strerror(errno)); - if (errno == EINTR) { - /* Only exit if the daemon has received QUIT/INT/TERM */ - free(events); - return 0; + ret = 0; } - free(events); - return -1; + if (ret < 0) + { + pr_error("poll error: %s\n", strerror(errno)); + } + + return ret; } - for (i = 0 ; i < n ; i++) + if (ev->pfd.revents == 0) { - int (*callback)() = events[i].data.ptr; + return 0; + } - if (!(events[i].events & (EPOLLIN | EPOLLET))) - { - pr_error("Error while polling. Event received: 0x%x\n", - events[i].events); - /* We only support one event producer. - * Error means that this producer died. - */ - pr_error("Now closing fd and exiting.\n"); - close(events[i].data.fd); - dlt_logstorage_exit(); - ret = -1; - break; - } + if (ev->pfd.events & EV_MASK_REJECTED) + { + pr_error("Error while polling. Event received: 0x%x\n", ev->pfd.events); + /* We only support one event producer. + * Error means that this producer died. + */ + pr_error("Now closing fd and exiting.\n"); + close(ev->pfd.fd); + ev->pfd.fd = -1; + dlt_logstorage_exit(); + return -1; + } - if (!callback) - { - pr_error("Callback not found, exiting.\n"); - dlt_logstorage_exit(); - ret = -1; - break; - } + if (!callback) + { + pr_error("Callback not found, exiting.\n"); + dlt_logstorage_exit(); + return -1; + } - pr_verbose("Got new event, calling %p.\n", callback); + pr_verbose("Got new event, calling %p.\n", callback); - if (callback() < 0) - { - pr_error("Error while calling the callback, exiting.\n"); - dlt_logstorage_exit(); - ret = -1; - break; - } + if (callback() < 0) + { + pr_error("Error while calling the callback, exiting.\n"); + dlt_logstorage_exit(); + return -1; } - free(events); - return ret; + return 0; } /** @brief Start event loop and receive messages from DLT. * * The function will first install the signal handler, - * then create the epoll instance, initialize the communication controller, + * then create the poll instance, initialize the communication controller, * initialize the event handler and finally start the polling. * * @return 0 on success, -1 on error @@ -323,18 +314,16 @@ static int dlt_logstorage_ctrl_execute_event_loop(int efd) static int dlt_logstorage_ctrl_setup_event_loop(void) { int ret = 0; + struct dlt_event ev_hdl = { + .pfd = { + .fd = -1, + .events = POLLIN + } + }; install_signal_handler(); - pr_verbose("Creating epoll instance.\n"); - efd = epoll_create1(0); - - if (efd == -1) - { - pr_error("epoll_create error: %s\n", strerror(errno)); - dlt_logstorage_exit(); - return -errno; - } + pr_verbose("Creating poll instance.\n"); /* Initializing the communication with the daemon */ while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && @@ -360,21 +349,20 @@ static int dlt_logstorage_ctrl_setup_event_loop(void) return -1; } - if (dlt_logstorage_ctrl_add_event(dlt_logstorage_get_handler_fd(), + if (dlt_logstorage_ctrl_add_event(&ev_hdl, + dlt_logstorage_get_handler_fd(), dlt_logstorage_get_handler_cb()) < 0) { - pr_error("epoll_ctl error: %s\n", strerror(errno)); + pr_error("add_event error: %s\n", strerror(errno)); dlt_logstorage_exit(); } while (!dlt_logstorage_must_exit() && (ret == 0)) { - ret = dlt_logstorage_ctrl_execute_event_loop(efd); + ret = dlt_logstorage_ctrl_execute_event_loop(&ev_hdl); } /* Clean up */ - close(efd); - dlt_logstorage_deinit_handler(); dlt_control_deinit(); @@ -561,6 +549,16 @@ static int parse_args(int argc, char *argv[]) return 0; } +#if !defined(DLT_SYSTEMD_ENABLE) +int sd_notify(int unset_environment, const char *state) +{ + /* Satisfy Compiler for warnings */ + (void) unset_environment; + (void) state; + return 0; +} +#endif + /** @brief Entry point * * Execute the argument parser and call the main feature accordingly. diff --git a/src/console/logstorage/dlt-logstorage-list.c b/src/console/logstorage/dlt-logstorage-list.c index 0b7a8c0..a18fca6 100644 --- a/src/console/logstorage/dlt-logstorage-list.c +++ b/src/console/logstorage/dlt-logstorage-list.c @@ -143,6 +143,7 @@ static struct LogstorageDeviceInfo *logstorage_find_dev_info(const char *node) int logstorage_store_dev_info(const char *node, const char *path) { struct LogstorageDeviceInfo *ptr = NULL; + size_t path_len = 0; if ((node == NULL) || (path == NULL)) { @@ -166,7 +167,21 @@ int logstorage_store_dev_info(const char *node, const char *path) } ptr->dev_node = strdup(node); - ptr->mnt_point = strndup(path, DLT_MOUNT_PATH_MAX); + path_len = strlen(path); + if (path_len >DLT_MOUNT_PATH_MAX) + { + path_len = (size_t)DLT_MOUNT_PATH_MAX; + } + ptr->mnt_point = (char *)calloc(1, path_len + 1); + + if (ptr->mnt_point == NULL) + { + pr_error("memory allocation failed for mnt_point\n"); + return -1; + } + + ptr->mnt_point[path_len] = '\0'; + memcpy(ptr->mnt_point, path, path_len); /* Put it on head */ ptr->next = g_info; diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index 2f5c27a..e9fb2ba 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -20,9 +20,22 @@ if(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) message( STATUS "Added ${systemd_SRCS} to dlt-daemon") endif(WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD) -set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c ${CMAKE_SOURCE_DIR}/src/gateway/dlt_gateway.c dlt_daemon_socket.c dlt_daemon_unix_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/lib/dlt_client.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_config_file_parser.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage_behavior.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_protocol.c) +set(dlt_daemon_SRCS dlt-daemon.c dlt_daemon_common.c dlt_daemon_connection.c dlt_daemon_event_handler.c ${CMAKE_SOURCE_DIR}/src/gateway/dlt_gateway.c dlt_daemon_socket.c dlt_daemon_unix_socket.c dlt_daemon_serial.c dlt_daemon_client.c dlt_daemon_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_offline_trace.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage.c ${CMAKE_SOURCE_DIR}/src/lib/dlt_client.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_config_file_parser.c ${CMAKE_SOURCE_DIR}/src/offlinelogstorage/dlt_offline_logstorage_behavior.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_protocol.c) + +if(WITH_DLT_SHM_ENABLE) + set(dlt_daemon_SRCS ${dlt_daemon_SRCS} ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c) +endif() + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(RT_LIBRARY rt) + set(SOCKET_LIBRARY "") +else() + set(RT_LIBRARY "") + set(SOCKET_LIBRARY socket) +endif() + add_executable(dlt-daemon ${dlt_daemon_SRCS} ${systemd_SRCS}) -target_link_libraries(dlt-daemon rt ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(dlt-daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS dlt-daemon RUNTIME DESTINATION bin @@ -33,7 +46,7 @@ install(TARGETS dlt-daemon if (WITH_DLT_UNIT_TESTS) add_library(dlt_daemon ${dlt_daemon_SRCS}) - target_link_libraries(dlt_daemon rt ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(dlt_daemon ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS dlt_daemon RUNTIME DESTINATION bin LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index 2cf8632..9956e3b 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -1049,7 +1049,7 @@ static int dlt_daemon_init_serial(DltDaemonLocal *daemon_local) return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, - EPOLLIN, + POLLIN, DLT_CONNECTION_CLIENT_MSG_SERIAL); } @@ -1121,7 +1121,7 @@ static int dlt_daemon_init_fifo(DltDaemonLocal *daemon_local) return dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, - EPOLLIN, + POLLIN, DLT_CONNECTION_APP_MSG); } #endif @@ -1159,7 +1159,7 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, - EPOLLIN, + POLLIN, DLT_CONNECTION_APP_CONNECT)) { dlt_log(LOG_CRIT, "Could not initialize app socket.\n"); @@ -1186,7 +1186,7 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, - EPOLLIN, + POLLIN, DLT_CONNECTION_CLIENT_CONNECT)) { dlt_log(LOG_ERR,"Could not initialize main socket.\n"); @@ -1211,7 +1211,7 @@ int dlt_daemon_local_connection_init(DltDaemon *daemon, if (dlt_connection_create(daemon_local, &daemon_local->pEvent, fd, - EPOLLIN, + POLLIN, DLT_CONNECTION_CONTROL_CONNECT)) { dlt_log(LOG_ERR, "Could not initialize control socket.\n"); @@ -1630,7 +1630,7 @@ int dlt_daemon_process_client_connect(DltDaemon *daemon, if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, - EPOLLIN, + POLLIN, DLT_CONNECTION_CLIENT_MSG_TCP)) { dlt_log(LOG_ERR, "Failed to register new client. \n"); @@ -1901,7 +1901,7 @@ int dlt_daemon_process_control_connect( if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, - EPOLLIN, + POLLIN, DLT_CONNECTION_CONTROL_MSG)) { dlt_log(LOG_ERR, "Failed to register new client. \n"); @@ -1956,7 +1956,7 @@ int dlt_daemon_process_app_connect( if (dlt_connection_create(daemon_local, &daemon_local->pEvent, in_sock, - EPOLLIN, + POLLIN, DLT_CONNECTION_APP_MSG)) { dlt_log(LOG_ERR, "Failed to register new application. \n"); @@ -2003,7 +2003,7 @@ int dlt_daemon_process_control_messages( /* FIXME: Why the hell do we need to close the socket * on control message reception ?? */ - //return 0; + return 0; } /* Process all received messages */ @@ -3422,7 +3422,7 @@ int create_timer_fd(DltDaemonLocal *daemon_local, return dlt_connection_create(daemon_local, &daemon_local->pEvent, local_fd, - EPOLLIN, + POLLIN, dlt_timer_conn_types[timer_id]); } diff --git a/src/daemon/dlt_daemon_connection.c b/src/daemon/dlt_daemon_connection.c index 8a3913a..619811d 100644 --- a/src/daemon/dlt_daemon_connection.c +++ b/src/daemon/dlt_daemon_connection.c @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include "dlt_daemon_connection_types.h" @@ -331,7 +331,7 @@ void dlt_connection_destroy(DltConnection *to_destroy) to_destroy->id = 0; close(to_destroy->receiver->fd); dlt_connection_destroy_receiver(to_destroy); - /* connection pointer might be in epoll queue and used even after destroying + /* connection pointer might be in poll queue and used even after destroying * it. To make sure it is not used anymore, connection type is invalidated */ to_destroy->type = DLT_CONNECTION_TYPE_MAX; free(to_destroy); @@ -370,7 +370,7 @@ int dlt_connection_create(DltDaemonLocal *daemon_local, /* No need for the same client to be registered twice * for the same event. * TODO: If another mask can be expected, - * we need it to update the epoll event here. + * we need it to update the poll event here. */ return 0; } diff --git a/src/daemon/dlt_daemon_connection_types.h b/src/daemon/dlt_daemon_connection_types.h index bd89998..68a0400 100644 --- a/src/daemon/dlt_daemon_connection_types.h +++ b/src/daemon/dlt_daemon_connection_types.h @@ -33,8 +33,8 @@ typedef enum { UNDEFINED, /* Undefined status */ - INACTIVE, /* Connection is inactive, excluded from epoll handling */ - ACTIVE, /* Connection is actively handled by epoll */ + INACTIVE, /* Connection is inactive, excluded from poll handling */ + ACTIVE, /* Connection is actively handled by poll */ DEACTIVATE,/* Request for deactivation of the connection */ ACTIVATE /* Request for activation of the connection */ } DltConnectionStatus; diff --git a/src/daemon/dlt_daemon_event_handler.c b/src/daemon/dlt_daemon_event_handler.c index 135130d..2410565 100644 --- a/src/daemon/dlt_daemon_event_handler.c +++ b/src/daemon/dlt_daemon_event_handler.c @@ -28,11 +28,12 @@ */ #include +#include #include #include -#include -#include +#include +#include #include "dlt_common.h" @@ -45,15 +46,31 @@ #include "dlt_daemon_event_handler_types.h" /** - * \def DLT_EPOLL_TIMEOUT_MSEC - * The maximum amount of time to wait for an epoll event. + * \def DLT_EV_TIMEOUT_MSEC + * The maximum amount of time to wait for a poll event. * Set to 1 second to avoid unnecessary wake ups. */ -#define DLT_EPOLL_TIMEOUT_MSEC 1000 +#define DLT_EV_TIMEOUT_MSEC 1000 +#define DLT_EV_BASE_FD 16 + +#define DLT_EV_MASK_REJECTED (POLLERR | POLLNVAL) + +/** @brief Initialize a pollfd structure + * + * That ensures that no event will be mis-watched. + * + * @param pfd: The element to initialize + */ +static void init_poll_fd(struct pollfd *pfd) +{ + pfd->fd = -1; + pfd->events = 0; + pfd->revents = 0; +} /** @brief Prepare the event handler * - * This will create the epoll file descriptor. + * This will create the base poll file descriptor list. * * @param ev The event handler to prepare. * @@ -61,21 +78,112 @@ */ int dlt_daemon_prepare_event_handling(DltEventHandler *ev) { + int i = 0; + if (ev == NULL) { return DLT_RETURN_ERROR; } - ev->epfd = epoll_create(DLT_EPOLL_MAX_EVENTS); - if (ev->epfd < 0) + ev->pfd = calloc(DLT_EV_BASE_FD, sizeof(struct pollfd)); + + if (ev->pfd == NULL) { - dlt_log(LOG_CRIT, "Creation of epoll instance failed!\n"); + dlt_log(LOG_CRIT, "Creation of poll instance failed!\n"); return -1; } + for (i = 0; i < DLT_EV_BASE_FD; i++) + { + init_poll_fd(&ev->pfd[i]); + } + + ev->nfds = 0; + ev->max_nfds = DLT_EV_BASE_FD; + return 0; } +/** @brief Enable a file descriptor to be watched + * + * Adds a file descriptor to the descriptor list. If the list is to small, + * increase its size. + * + * @param ev: The event handler structure, containing the list + * @param fd: The file descriptor to add + * @param mask: The mask of event to be watched + */ +static void dlt_event_handler_enable_fd(DltEventHandler *ev, int fd, int mask) +{ + if (ev->max_nfds <= ev->nfds) + { + int i = ev->nfds; + int max = 2 * ev->max_nfds; + struct pollfd *tmp = realloc(ev->pfd, max * sizeof(*ev->pfd)); + + if (!tmp) + { + dlt_log(LOG_CRIT, + "Unable to register new fd for the event handler.\n"); + return; + } + + ev->pfd = tmp; + ev->max_nfds = max; + + for (; i < max; i++) + { + init_poll_fd(&ev->pfd[i]); + } + } + + ev->pfd[ev->nfds].fd = fd; + ev->pfd[ev->nfds].events = mask; + ev->nfds++; +} + +/** @brief Disable a file descriptor for watching + * + * The file descriptor is removed from the descriptor list, the list is + * compressed during the process. + * + * @param ev: The event handler structure containing the list + * @param fd: The file descriptor to be removed + */ +static void dlt_event_handler_disable_fd(DltEventHandler *ev, int fd) +{ + unsigned int i = 0; + unsigned int j = 0; + unsigned int nfds = ev->nfds; + + for (; i < nfds; i++, j++) + { + if (ev->pfd[i].fd == fd) + { + init_poll_fd(&ev->pfd[i]); + j++; + ev->nfds--; + } + + if (i == j) + { + continue; + } + + /* Compressing the table */ + if (i < ev->nfds) + { + ev->pfd[i].fd = ev->pfd[j].fd; + ev->pfd[i].events = ev->pfd[j].events; + ev->pfd[i].revents = ev->pfd[j].revents; + } + else + { + init_poll_fd(&ev->pfd[i]); + } + } +} + /** @brief Catch and process incoming events. * * This function waits for events on all connections. Once an event raise, @@ -92,48 +200,49 @@ int dlt_daemon_handle_event(DltEventHandler *pEvent, DltDaemon *daemon, DltDaemonLocal *daemon_local) { + int ret = 0; + unsigned int i = 0; + char str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' }; + int (*callback)(DltDaemon *, DltDaemonLocal *, DltReceiver *, int) = NULL; + if ((pEvent == NULL) || (daemon == NULL) || (daemon_local == NULL)) { return DLT_RETURN_ERROR; } - int nfds = 0; - int i = 0; - char str[DLT_DAEMON_TEXTBUFSIZE]; - int (*callback)(DltDaemon *, DltDaemonLocal *, DltReceiver *, int) = NULL; - /*CM Change begin*/ - nfds = epoll_wait(pEvent->epfd, - pEvent->events, - DLT_EPOLL_MAX_EVENTS, - DLT_EPOLL_TIMEOUT_MSEC); + ret = poll(pEvent->pfd, pEvent->nfds, DLT_EV_TIMEOUT_MSEC); - if (nfds < 0) + if (ret <= 0) { /* We are not interested in EINTR has it comes * either from timeout or signal. */ - if (errno != EINTR) + if (errno == EINTR) { - snprintf(str, - DLT_DAEMON_TEXTBUFSIZE, - "epoll_wait() failed: %s\n", - strerror(errno)); - dlt_log(LOG_CRIT, str); - return -1; + ret = 0; + } + + if (ret < 0) + { + dlt_vlog(LOG_CRIT, "poll() failed: %s\n", strerror(errno)); } - return 0; + return ret; } - for (i = 0 ; i < nfds ; i++) + for (i = 0 ; i < pEvent->nfds ; i++) { - struct epoll_event *ev = &pEvent->events[i]; - DltConnectionId id = (DltConnectionId)ev->data.ptr; - DltConnection *con = dlt_event_handler_find_connection_by_id(pEvent, - id); int fd = 0; + DltConnection *con = NULL; DltConnectionType type = DLT_CONNECTION_TYPE_MAX; + if (pEvent->pfd[i].revents == 0) + { + continue; + } + + con = dlt_event_handler_find_connection(pEvent, pEvent->pfd[i].fd); + if (con && con->receiver) { type = con->type; @@ -141,17 +250,15 @@ int dlt_daemon_handle_event(DltEventHandler *pEvent, } else /* connection might have been destroyed in the meanwhile */ { + dlt_event_handler_disable_fd(pEvent, pEvent->pfd[i].fd); continue; } - /* First of all handle epoll error events - * We only expect EPOLLIN or EPOLLOUT - */ - if ((ev->events != EPOLLIN) && (ev->events != EPOLLOUT)) + /* First of all handle error events */ + if (pEvent->pfd[i].revents & DLT_EV_MASK_REJECTED) { - /* epoll reports an error, we need to clean-up the concerned event + /* An error occurred, we need to clean-up the concerned event */ - if (type == DLT_CONNECTION_CLIENT_MSG_TCP) { /* To transition to BUFFER state if this is final TCP client connection, @@ -224,31 +331,6 @@ DltConnection *dlt_event_handler_find_connection(DltEventHandler *ev, return temp; } -/** @brief Find connection with a specific \a id in the connection list. - * - * There can be only one event per \a fd. We can then find a specific connection - * based on this \a fd. That allows to check if a specific \a fd has already been - * registered. - * - * @param ev The event handler structure where the list of connection is. - * @param id The identifier of the connection to be found. - * - * @return The found connection pointer, NULL otherwise. - */ -DltConnection *dlt_event_handler_find_connection_by_id(DltEventHandler *ev, - DltConnectionId id) -{ - - DltConnection *temp = ev->connections; - - while ((temp != NULL) && (temp->id != id)) - { - temp = temp->next; - } - - return temp; -} - /** @brief Remove a connection from the list and destroy it. * * This function will first look for the connection in the event handler list, @@ -306,6 +388,8 @@ STATIC int dlt_daemon_remove_connection(DltEventHandler *ev, */ void dlt_event_handler_cleanup_connections(DltEventHandler *ev) { + unsigned int i = 0; + if (ev == NULL) { /* Nothing to do. */ @@ -317,6 +401,13 @@ void dlt_event_handler_cleanup_connections(DltEventHandler *ev) /* We don really care on failure */ (void)dlt_daemon_remove_connection(ev, ev->connections); } + + for (i = 0; i < ev->nfds; i++) + { + init_poll_fd(&ev->pfd[i]); + } + + free(ev->pfd); } /** @brief Add a new connection to the list. @@ -381,14 +472,7 @@ int dlt_connection_check_activate(DltEventHandler *evhdl, con->type); dlt_log(LOG_INFO, local_str); - if (epoll_ctl(evhdl->epfd, - EPOLL_CTL_DEL, - con->receiver->fd, - NULL) == -1) - { - dlt_log(LOG_ERR, "epoll_ctl() in deactivate failed!\n"); - return -1; - } + dlt_event_handler_disable_fd(evhdl, con->receiver->fd); con->status = INACTIVE; } @@ -396,25 +480,16 @@ int dlt_connection_check_activate(DltEventHandler *evhdl, case INACTIVE: if (activation_type == ACTIVATE) { - struct epoll_event ev; /* Content will be copied by the kernel */ - ev.events = con->ev_mask; - ev.data.ptr = (void *)con->id; - snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Activate connection type: %d\n", con->type); dlt_log(LOG_INFO, local_str); + dlt_event_handler_enable_fd(evhdl, + con->receiver->fd, + con->ev_mask); - if (epoll_ctl(evhdl->epfd, - EPOLL_CTL_ADD, - con->receiver->fd, - &ev) == -1) - { - dlt_log(LOG_ERR, "epoll_ctl() in activate failed!\n"); - return -1; - } con->status = ACTIVE; } break; @@ -447,11 +522,12 @@ int dlt_connection_check_activate(DltEventHandler *evhdl, * @return 0 on success, -1 otherwise. */ int dlt_event_handler_register_connection(DltEventHandler *evhdl, - DltDaemonLocal *daemon_local, - DltConnection *connection, - int mask) + DltDaemonLocal *daemon_local, + DltConnection *connection, + int mask) { - if (!evhdl || !connection || !connection->receiver) { + if (!evhdl || !connection || !connection->receiver) + { dlt_log(LOG_ERR, "Wrong parameters when registering connection.\n"); return -1; } @@ -490,8 +566,8 @@ int dlt_event_handler_register_connection(DltEventHandler *evhdl, * @return 0 on success, -1 otherwise. */ int dlt_event_handler_unregister_connection(DltEventHandler *evhdl, - DltDaemonLocal *daemon_local, - int fd) + DltDaemonLocal *daemon_local, + int fd) { if (evhdl == NULL || daemon_local == NULL) { diff --git a/src/daemon/dlt_daemon_event_handler.h b/src/daemon/dlt_daemon_event_handler.h index dc91b89..280bfd7 100644 --- a/src/daemon/dlt_daemon_event_handler.h +++ b/src/daemon/dlt_daemon_event_handler.h @@ -27,7 +27,7 @@ * \file dlt_daemon_event_handler.h */ -#include +#include #include "dlt_daemon_connection_types.h" #include "dlt_daemon_event_handler_types.h" diff --git a/src/daemon/dlt_daemon_event_handler_types.h b/src/daemon/dlt_daemon_event_handler_types.h index a2945b4..99a1217 100644 --- a/src/daemon/dlt_daemon_event_handler_types.h +++ b/src/daemon/dlt_daemon_event_handler_types.h @@ -27,7 +27,7 @@ * \file dlt_daemon_event_handler_types.h */ -#include +#include #include "dlt_daemon_connection_types.h" @@ -50,10 +50,10 @@ typedef enum { DLT_TIMER_UNKNOWN } DltTimers; -#define DLT_EPOLL_MAX_EVENTS 10 typedef struct { - int epfd; - struct epoll_event events[DLT_EPOLL_MAX_EVENTS]; + struct pollfd *pfd; + nfds_t nfds; + nfds_t max_nfds; DltConnection *connections; } DltEventHandler; diff --git a/src/gateway/dlt_gateway.c b/src/gateway/dlt_gateway.c index c5203db..4236d23 100644 --- a/src/gateway/dlt_gateway.c +++ b/src/gateway/dlt_gateway.c @@ -868,11 +868,11 @@ STATIC int dlt_gateway_add_to_event_loop(DltDaemonLocal *daemon_local, con->timeout_cnt = 0; con->sendtime_cnt = 0; - /* setup dlt connection and add to epoll event loop here */ + /* setup dlt connection and add to poll event loop here */ if (dlt_connection_create(daemon_local, &daemon_local->pEvent, con->client.sock, - EPOLLIN, + POLLIN, DLT_CONNECTION_GATEWAY) != 0) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); @@ -947,7 +947,7 @@ int dlt_gateway_establish_connections(DltGateway *gateway, if (ret == 0) { - /* setup dlt connection and add to epoll event loop here */ + /* setup dlt connection and add to poll event loop here */ if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); @@ -972,11 +972,11 @@ int dlt_gateway_establish_connections(DltGateway *gateway, else if ((con->status == DLT_GATEWAY_CONNECTED) && (con->trigger != DLT_GATEWAY_DISABLED)) { - /* setup dlt connection and add to epoll event loop here */ + /* setup dlt connection and add to poll event loop here */ if (dlt_connection_create(daemon_local, &daemon_local->pEvent, con->client.sock, - EPOLLIN, + POLLIN, DLT_CONNECTION_GATEWAY) != 0) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); @@ -1672,7 +1672,7 @@ int dlt_gateway_process_on_demand_request(DltGateway *gateway, { if (dlt_client_connect(&con->client, verbose) == 0) { - /* setup dlt connection and add to epoll event loop here */ + /* setup dlt connection and add to poll event loop here */ if (dlt_gateway_add_to_event_loop(daemon_local, con, verbose) != DLT_RETURN_OK) { dlt_log(LOG_ERR, "Gateway connection creation failed\n"); diff --git a/src/gateway/dlt_gateway.h b/src/gateway/dlt_gateway.h index 2da2118..c3c7324 100644 --- a/src/gateway/dlt_gateway.h +++ b/src/gateway/dlt_gateway.h @@ -84,7 +84,7 @@ void dlt_gateway_deinit(DltGateway *g, int verbose); * on daemon startup and add this connections to the main event loop. * * TODO: This function is called during gateway initialization and in main loop - * whenever the epoll returns. This may need to be improved. + * whenever the poll returns. This may need to be improved. * * @param g DltGateway * @param daemon_local DltDaemonLocal diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index d20d954..537e2ca 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -15,10 +15,23 @@ # @licence end@ ####### -set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer dlt_env_ll ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_protocol.c) +set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer dlt_env_ll ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_protocol.c) + +if(WITH_DLT_SHM_ENABLE) + set(dlt_LIB_SRCS ${dlt_LIB_SRCS} ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c) +endif(WITH_DLT_SHM_ENABLE) add_library(dlt ${dlt_LIB_SRCS}) -target_link_libraries(dlt rt ${CMAKE_THREAD_LIBS_INIT}) + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(RT_LIBRARY rt) + set(SOCKET_LIBRARY "") +else() + set(RT_LIBRARY "") + set(SOCKET_LIBRARY socket) +endif() + +target_link_libraries(dlt ${RT_LIBRARY} ${SOCKET_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties(dlt PROPERTIES VERSION ${DLT_VERSION} SOVERSION ${DLT_MAJOR_VERSION}) diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index ab92c2d..0e4c42b 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -196,6 +196,7 @@ static DltReturnValue dlt_initialize_socket_connection(void) struct sockaddr_un remote; int status = 0; char dltSockBaseDir[DLT_IPC_PATH_MAX]; + struct linger l_opt; DLT_SEM_LOCK(); int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -216,6 +217,15 @@ static DltReturnValue dlt_initialize_socket_connection(void) return DLT_RETURN_ERROR; } + /* Set SO_LINGER opt for the new client socket. */ + l_opt.l_onoff = 1; + l_opt.l_linger = 10; + + if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &l_opt, sizeof l_opt) < 0) + { + dlt_log(LOG_WARNING, "Failed to set linger option\n"); + } + remote.sun_family = AF_UNIX; snprintf(dltSockBaseDir, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH); strncpy(remote.sun_path, dltSockBaseDir, sizeof(dltSockBaseDir)); @@ -1225,6 +1235,27 @@ DltReturnValue dlt_unregister_app(void) return ret; } +DltReturnValue dlt_unregister_app_flush_buffered_logs(void) +{ + DltReturnValue ret = DLT_RETURN_OK; + + if (!dlt_user_initialised) + { + dlt_vlog(LOG_ERR, "%s dlt_user_initialised false\n", __func__); + return DLT_RETURN_ERROR; + } + + if (dlt_user.dlt_log_handle != -1) + { + do + { + ret = dlt_user_log_resend_buffer(); + }while ((ret != DLT_RETURN_OK) && (dlt_user.dlt_log_handle != -1)); + } + + return dlt_unregister_app(); +} + DltReturnValue dlt_unregister_context(DltContext *handle) { DltContextData log; @@ -2714,7 +2745,7 @@ DltReturnValue dlt_user_trace_network_segmented_segment(uint32_t id, DltContext } /* Allow other threads to log between chunks */ - pthread_yield(); + sched_yield(); return DLT_RETURN_OK; } @@ -4430,12 +4461,12 @@ DltReturnValue dlt_user_log_resend_buffer(void) { int num,count; int size; - DltReturnValue ret; - - if (dlt_user.appID[0]=='\0') - { - return 0; - } + DltReturnValue ret; + + if (dlt_user.appID[0]=='\0') + { + return 0; + } /* Send content of ringbuffer */ DLT_SEM_LOCK(); @@ -4511,7 +4542,6 @@ DltReturnValue dlt_user_log_resend_buffer(void) void dlt_user_log_reattach_to_daemon(void) { uint32_t num, reregistered = 0; - DltContext handle; DltContextData log_new; diff --git a/src/shared/dlt_common.c b/src/shared/dlt_common.c index 9f8d60e..d2f86f4 100644 --- a/src/shared/dlt_common.c +++ b/src/shared/dlt_common.c @@ -3166,6 +3166,7 @@ speed_t dlt_convert_serial_speed(int baudrate) ret = B115200; break; } +#ifdef __linux__ case 230400: { ret = B230400; @@ -3231,6 +3232,7 @@ speed_t dlt_convert_serial_speed(int baudrate) ret = B4000000; break; } +#endif /* __linux__ */ default: { ret = B115200; diff --git a/src/tests/dlt-test-multi-process.c b/src/tests/dlt-test-multi-process.c index c5c8ddd..0726b9a 100644 --- a/src/tests/dlt-test-multi-process.c +++ b/src/tests/dlt-test-multi-process.c @@ -62,6 +62,10 @@ #define MAX_PROCS 100 #define MAX_THREADS 100 +#ifndef WAIT_ANY +#define WAIT_ANY -1 +#endif + // Structs typedef struct { int nmsgs; // Number of messages to send -- cgit v1.2.1