From: Sung-Jin Park Date: Mon, 20 May 2019 11:44:50 +0000 (+0900) Subject: headless_debug: add debug features X-Git-Tag: submit/tizen/20190530.092249~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=138d081087571763432d49b05182f0a2d565e218;p=platform%2Fcore%2Fuifw%2Fpepper.git headless_debug: add debug features headless_debug provides some debug features such as wayland protocol trace (event trace), redirection of STDOUT/STDERR, displaying keygrab status, top-visible stack of windows and connected clients information. Intially, enabling/disabling event trace features and redirection have been added. The rest of the features will be added soon. Change-Id: I800249045e785988a59fd2e5b904c98a00436e3f Signed-off-by: Sung-Jin Park --- diff --git a/data/units/display-manager.service.headless b/data/units/display-manager.service.headless index 35ecc6b..5b4663d 100644 --- a/data/units/display-manager.service.headless +++ b/data/units/display-manager.service.headless @@ -5,6 +5,7 @@ Description=Headless Display Manager Type=simple EnvironmentFile=/etc/sysconfig/display-manager.env SmackProcessLabel=System +ExecStartPre=/usr/bin/bash -c "/usr/bin/mkdir -p ${XDG_RUNTIME_DIR}/pepper/" ExecStart=/usr/bin/headless_server [Install] diff --git a/src/bin/headless/Makefile.am b/src/bin/headless/Makefile.am index 88e6f44..1cdb324 100644 --- a/src/bin/headless/Makefile.am +++ b/src/bin/headless/Makefile.am @@ -6,6 +6,7 @@ headless_server_CFLAGS = $(HEADLESS_SERVER_CFLAGS) headless_server_LDADD = $(HEADLESS_SERVER_LIBS) headless_server_SOURCES = headless_server.c \ + debug/debug.c \ input/input.c \ output/output_led.c \ output/HL_UI_LED_APA102.c \ diff --git a/src/bin/headless/debug/debug.c b/src/bin/headless/debug/debug.c new file mode 100644 index 0000000..e840822 --- /dev/null +++ b/src/bin/headless/debug/debug.c @@ -0,0 +1,273 @@ +/* +* Copyright © 2018 Samsung Electronics co., Ltd. All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_CMDS 256 + +#define STDOUT_REDIR "stdout" +#define STDERR_REDIR "stderr" +#define EVENT_TRACE_ON "event_trace_on" +#define EVENT_TRACE_OFF "event_trace_off" +#define KEYGRAB_STATUS "keygrab_status" +#define TOPVWINS "topvwins" +#define CONNECT_CLIENTS "connect_clients" +#define HELP_MSG "help" + +extern void wl_debug_server_enable(int enable); + +typedef struct +{ + pepper_compositor_t *compositor; + pepper_inotify_t *inotify; +} headless_debug_t; + +typedef void (*headless_debug_action_cb_t)(headless_debug_t *hd, void *data); + +typedef struct +{ + const char *cmds; + headless_debug_action_cb_t cb; + headless_debug_action_cb_t disable_cb; +} headless_debug_action_t; + +const static int KEY_DEBUG = 0xdeaddeb0; + +static void +_headless_debug_usage() +{ + fprintf(stdout, "Commands:\n\n"); + fprintf(stdout, "\t %s\n", EVENT_TRACE_ON); + fprintf(stdout, "\t %s\n", EVENT_TRACE_OFF); + fprintf(stdout, "\t %s\n", STDOUT_REDIR); + fprintf(stdout, "\t %s\n", STDERR_REDIR); + fprintf(stdout, "\t %s\n", KEYGRAB_STATUS); + fprintf(stdout, "\t %s\n", TOPVWINS); + fprintf(stdout, "\t %s\n", CONNECT_CLIENTS); + fprintf(stdout, "\t %s\n", HELP_MSG); + + fprintf(stdout, "\nTo execute commands, just create/remove/update a file with the commands above.\n"); + fprintf(stdout, "Please refer to the following examples.\n\n"); + fprintf(stdout, "\t touch %s to enable event trace\n", EVENT_TRACE_ON); + fprintf(stdout, "\t rm -f %s to disable event trace\n", EVENT_TRACE_ON); + fprintf(stdout, "\t touch %s to disable event trace\n", EVENT_TRACE_OFF); + fprintf(stdout, "\t touch stdout to redirect STDOUT to stdout.txt\n"); + fprintf(stdout, "\t touch stderr to redirect STDERR to stderr.txt\n"); +} + +static void +_headless_debug_event_trace_on(headless_debug_t *hdebug, void *data) +{ + (void) hdebug; + (void) data; + wl_debug_server_enable(1); +} + +static void +_headless_debug_event_trace_off(headless_debug_t *hdebug, void *data) +{ + (void) hdebug; + (void) data; + wl_debug_server_enable(0); +} + +static void +_headless_debug_dummy(headless_debug_t *hdebug, void *data) +{ + (void) hdebug; + (void) data; + _headless_debug_usage(); +} + +static void +_headless_debug_redir_stdout(headless_debug_t *hdebug, void *data) +{ + (void) hdebug; + (void) data; + + static int fd = -1; + + if (fd >= 0) + close(fd); + + fd = open("/run/pepper/stdout.txt", O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IWGRP); + + if (fd < 0) { + PEPPER_TRACE("Failed to open stdout.txt (errno=%s)\n", strerror(errno)); + return; + } + + dup2(fd, 1); + PEPPER_TRACE("STDOUT has been redirected to stdout.txt.\n"); +} + +static void +_headless_debug_redir_stderr(headless_debug_t *hdebug, void *data) +{ + (void) hdebug; + (void) data; + + static int fd = -1; + + if (fd >= 0) + close(fd); + + fd = open("/run/pepper/stderr.txt", O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IWGRP); + + if (fd < 0) { + PEPPER_TRACE("Failed to open stderr.txt (errno=%s)\n", strerror(errno)); + return; + } + + dup2(fd, 2); + PEPPER_TRACE("STDERR has been redirected to stderr.txt.\n"); + +} + +static const headless_debug_action_t debug_actions[] = +{ + { STDOUT_REDIR, _headless_debug_redir_stdout, NULL }, + { STDERR_REDIR, _headless_debug_redir_stderr, NULL }, + { EVENT_TRACE_ON, _headless_debug_event_trace_on, _headless_debug_event_trace_off }, + { EVENT_TRACE_OFF, _headless_debug_event_trace_off, NULL }, + { KEYGRAB_STATUS, _headless_debug_dummy, NULL }, + { TOPVWINS, _headless_debug_dummy, NULL }, + { CONNECT_CLIENTS, _headless_debug_dummy, NULL }, + { HELP_MSG, _headless_debug_dummy, NULL }, +}; + +static void +_headless_debug_enable_action(headless_debug_t *hdebug, char *cmds) +{ + int n_actions = sizeof(debug_actions)/sizeof(debug_actions[0]); + + for(int n=0 ; n < n_actions ; n++) { + if (!strncmp(cmds, debug_actions[n].cmds, MAX_CMDS)) { + debug_actions[n].cb(hdebug, (void *)debug_actions[n].cmds); + PEPPER_TRACE("[%s : %s]\n", __FUNCTION__, debug_actions[n].cmds); + + break; + } + } +} + +static void +_headless_debug_disable_action(headless_debug_t *hdebug, char *cmds) +{ + int n_actions = sizeof(debug_actions)/sizeof(debug_actions[0]); + + for(int n=0 ; n < n_actions ; n++) { + if (!strncmp(cmds, debug_actions[n].cmds, MAX_CMDS)) { + if (debug_actions[n].disable_cb) { + debug_actions[n].disable_cb(hdebug, (void *)debug_actions[n].cmds); + PEPPER_TRACE("[%s : %s]\n", __FUNCTION__, debug_actions[n].cmds); + } + + break; + } + } +} + +static void +_trace_cb_handle_inotify_event(uint32_t type, pepper_inotify_event_t *ev, void *data) +{ + headless_debug_t *hdebug = data; + char *file_name = pepper_inotify_event_name_get(ev); + + PEPPER_CHECK(hdebug, return, "Invalid headless debug instance\n"); + + switch (type) + { + case PEPPER_INOTIFY_EVENT_TYPE_CREATE: + _headless_debug_enable_action(hdebug, file_name); + break; + case PEPPER_INOTIFY_EVENT_TYPE_REMOVE: + _headless_debug_disable_action(hdebug, file_name); + break; + case PEPPER_INOTIFY_EVENT_TYPE_MODIFY: + _headless_debug_enable_action(hdebug, file_name); + break; + + default: + PEPPER_TRACE("[%s] Unhandled event type (%d)\n", __FUNCTION__, type); + break; + } +} + +PEPPER_API void +headless_debug_deinit(pepper_compositor_t * compositor) +{ + headless_debug_t *hdebug = NULL; + + hdebug = (headless_debug_t *)pepper_object_get_user_data((pepper_object_t *) compositor, &KEY_DEBUG); + PEPPER_CHECK(hdebug, return, "Failed to get headless debug instance\n"); + + /* remove the directory watching already */ + if (hdebug->inotify) + pepper_inotify_del(hdebug->inotify, "/run/pepper"); + + /* remove inotify */ + pepper_inotify_destroy(hdebug->inotify); + hdebug->inotify = NULL; + + pepper_object_set_user_data((pepper_object_t *)hdebug->compositor, &KEY_DEBUG, NULL, NULL); + free(hdebug); +} + +pepper_bool_t +headless_debug_init(pepper_compositor_t *compositor) +{ + headless_debug_t *hdebug = NULL; + pepper_inotify_t *inotify = NULL; + pepper_bool_t res = PEPPER_FALSE; + + hdebug = (headless_debug_t*)calloc(1, sizeof(headless_debug_t)); + PEPPER_CHECK(hdebug, goto error, "Failed to alloc for headless debug\n"); + hdebug->compositor = compositor; + + /* create inotify to watch file(s) for event trace */ + inotify = pepper_inotify_create(hdebug->compositor, _trace_cb_handle_inotify_event, hdebug); + PEPPER_CHECK(inotify, goto error, "Failed to create inotify\n"); + + /* add a directory for watching */ + res = pepper_inotify_add(inotify, "/run/pepper"); + PEPPER_CHECK(res, goto error, "Failed on pepper_inotify_add()\n"); + + hdebug->inotify = inotify; + + PEPPER_TRACE("[%s] ... done\n", __FUNCTION__); + + pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_DEBUG, hdebug, NULL); + return PEPPER_TRUE; + +error: + headless_debug_deinit(compositor); + + return PEPPER_FALSE; +} diff --git a/src/bin/headless/headless_server.c b/src/bin/headless/headless_server.c index 99a81be..1627589 100644 --- a/src/bin/headless/headless_server.c +++ b/src/bin/headless/headless_server.c @@ -57,6 +57,10 @@ int main(int argc, char *argv[]) compositor = pepper_compositor_create(socket_name); PEPPER_CHECK(compositor, return EXIT_FAILURE, "Failed to create compositor !"); + /* Init event trace */ + ret = headless_debug_init(compositor); + PEPPER_CHECK(ret, goto end, "headless_debug_init() failed\n"); + /* Init input for headless */ ret = headless_input_init(compositor); PEPPER_CHECK(ret, goto end, "headless_input_init() failed\n"); @@ -80,6 +84,7 @@ end: headless_shell_deinit(compositor); headless_input_deinit(compositor); headless_output_deinit(compositor); + headless_debug_deinit(compositor); pepper_compositor_destroy(compositor); return EXIT_SUCCESS; diff --git a/src/bin/headless/headless_server.h b/src/bin/headless/headless_server.h index 7a72496..42f28ef 100644 --- a/src/bin/headless/headless_server.h +++ b/src/bin/headless/headless_server.h @@ -44,6 +44,10 @@ PEPPER_API void headless_input_deinit(pepper_compositor_t *compositor); PEPPER_API void headless_input_set_focus_view(pepper_compositor_t *compositor, pepper_view_t *view); PEPPER_API void headless_input_set_top_view(pepper_compositor_t *compositor, pepper_view_t *view); +/* APIs for headless_debug */ +PEPPER_API pepper_bool_t headless_debug_init(pepper_compositor_t *compositor); +PEPPER_API void headless_debug_deinit(pepper_compositor_t *compositor); + #ifdef __cplusplus } #endif