2 * Copyright (c) 2024 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup taskmon
40 #include <ipc/services.h>
41 #include <ipc/corecfg.h>
46 #include <str_error.h>
49 #define NAME "taskmon"
51 static const char *taskmon_cfg_path
= "/w/cfg/taskmon.sif";
53 static bool write_core_files
;
55 static errno_t
taskmon_load_cfg(const char *);
56 static errno_t
taskmon_save_cfg(const char *);
57 static void corecfg_client_conn(ipc_call_t
*, void *);
59 static void fault_event(ipc_call_t
*call
, void *arg
)
69 taskid
= MERGE_LOUP32(ipc_get_arg1(call
), ipc_get_arg2(call
));
70 thread
= ipc_get_arg3(call
);
72 if (asprintf(&s_taskid
, "%" PRIu64
, taskid
) < 0) {
73 printf("Memory allocation failed.\n");
77 printf(NAME
": Task %" PRIu64
" fault in thread %p.\n", taskid
,
80 fname
= "/app/taskdump";
82 if (write_core_files
) {
83 if (asprintf(&dump_fname
, "/data/core%" PRIu64
, taskid
) < 0) {
84 printf("Memory allocation failed.\n");
88 printf(NAME
": Executing %s -c %s -t %s\n", fname
, dump_fname
, s_taskid
);
89 rc
= task_spawnl(NULL
, NULL
, fname
, fname
, "-c", dump_fname
, "-t", s_taskid
,
92 printf(NAME
": Executing %s -t %s\n", fname
, s_taskid
);
93 rc
= task_spawnl(NULL
, NULL
, fname
, fname
, "-t", s_taskid
, NULL
);
97 printf("%s: Error spawning %s (%s).\n", NAME
, fname
,
102 static void corecfg_get_enable_srv(ipc_call_t
*icall
)
104 async_answer_1(icall
, EOK
, write_core_files
);
107 static void corecfg_set_enable_srv(ipc_call_t
*icall
)
109 write_core_files
= ipc_get_arg1(icall
);
110 async_answer_0(icall
, EOK
);
111 (void) taskmon_save_cfg(taskmon_cfg_path
);
114 static void corecfg_client_conn(ipc_call_t
*icall
, void *arg
)
116 /* Accept the connection */
117 async_accept_0(icall
);
121 async_get_call(&call
);
122 sysarg_t method
= ipc_get_imethod(&call
);
125 /* The other side has hung up */
126 async_answer_0(&call
, EOK
);
131 case CORECFG_GET_ENABLE
:
132 corecfg_get_enable_srv(&call
);
134 case CORECFG_SET_ENABLE
:
135 corecfg_set_enable_srv(&call
);
138 async_answer_0(&call
, ENOTSUP
);
143 /** Load task monitor configuration from SIF file.
145 * @param cfgpath Configuration file path
147 * @return EOK on success or an error code
149 static errno_t
taskmon_load_cfg(const char *cfgpath
)
151 sif_doc_t
*doc
= NULL
;
153 sif_node_t
*ncorefiles
;
158 rc
= sif_load(cfgpath
, &doc
);
162 rnode
= sif_get_root(doc
);
163 ncorefiles
= sif_node_first_child(rnode
);
164 ntype
= sif_node_get_type(ncorefiles
);
165 if (str_cmp(ntype
, "corefiles") != 0) {
170 swrite
= sif_node_get_attr(ncorefiles
, "write");
171 if (swrite
== NULL
) {
176 if (str_cmp(swrite
, "y") == 0) {
177 write_core_files
= true;
178 } else if (str_cmp(swrite
, "n") == 0) {
179 write_core_files
= false;
193 /** Save task monitor configuration to SIF file.
195 * @param cfgpath Configuration file path
197 * @return EOK on success or an error code
199 static errno_t
taskmon_save_cfg(const char *cfgpath
)
201 sif_doc_t
*doc
= NULL
;
203 sif_node_t
*ncorefiles
;
210 rnode
= sif_get_root(doc
);
211 rc
= sif_node_append_child(rnode
, "corefiles", &ncorefiles
);
215 rc
= sif_node_set_attr(ncorefiles
, "write",
216 write_core_files
? "y" : "n");
220 rc
= sif_save(doc
, cfgpath
);
232 int main(int argc
, char *argv
[])
236 printf("%s: Task Monitoring Service\n", NAME
);
238 #ifdef CONFIG_WRITE_CORE_FILES
239 write_core_files
= true;
241 write_core_files
= false;
243 (void) taskmon_load_cfg(taskmon_cfg_path
);
245 if (async_event_subscribe(EVENT_FAULT
, fault_event
, NULL
) != EOK
) {
246 printf("%s: Error registering fault notifications.\n", NAME
);
250 async_set_fallback_port_handler(corecfg_client_conn
, NULL
);
252 errno_t rc
= loc_server_register(NAME
, &srv
);
254 printf("%s: Failed registering server: %s.\n",
255 NAME
, str_error(rc
));
260 rc
= loc_service_register(srv
, SERVICE_NAME_CORECFG
, &sid
);
262 loc_server_unregister(srv
);
263 printf("%s: Failed registering service: %s.\n",
264 NAME
, str_error(rc
));