source: mainline/uspace/srv/taskmon/taskmon.c@ f0cc1c64

Last change on this file since f0cc1c64 was ca48672, checked in by Jiri Svoboda <jiri@…>, 8 days ago

loc_service_register() needs to take a port ID argument.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup taskmon
30 * @brief
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <async.h>
38#include <errno.h>
39#include <macros.h>
40#include <ipc/services.h>
41#include <ipc/corecfg.h>
42#include <loc.h>
43#include <sif.h>
44#include <stdio.h>
45#include <str.h>
46#include <str_error.h>
47#include <task.h>
48
49#define NAME "taskmon"
50
51static const char *taskmon_cfg_path = "/w/cfg/taskmon.sif";
52
53static bool write_core_files;
54
55static errno_t taskmon_load_cfg(const char *);
56static errno_t taskmon_save_cfg(const char *);
57static void corecfg_client_conn(ipc_call_t *, void *);
58
59static void fault_event(ipc_call_t *call, void *arg)
60{
61 const char *fname;
62 char *s_taskid;
63 char *dump_fname;
64 errno_t rc;
65
66 task_id_t taskid;
67 uintptr_t thread;
68
69 taskid = MERGE_LOUP32(ipc_get_arg1(call), ipc_get_arg2(call));
70 thread = ipc_get_arg3(call);
71
72 if (asprintf(&s_taskid, "%" PRIu64, taskid) < 0) {
73 printf("Memory allocation failed.\n");
74 return;
75 }
76
77 printf(NAME ": Task %" PRIu64 " fault in thread %p.\n", taskid,
78 (void *) thread);
79
80 fname = "/app/taskdump";
81
82 if (write_core_files) {
83 if (asprintf(&dump_fname, "/data/core%" PRIu64, taskid) < 0) {
84 printf("Memory allocation failed.\n");
85 return;
86 }
87
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,
90 NULL);
91 } else {
92 printf(NAME ": Executing %s -t %s\n", fname, s_taskid);
93 rc = task_spawnl(NULL, NULL, fname, fname, "-t", s_taskid, NULL);
94 }
95
96 if (rc != EOK) {
97 printf("%s: Error spawning %s (%s).\n", NAME, fname,
98 str_error(rc));
99 }
100}
101
102static void corecfg_get_enable_srv(ipc_call_t *icall)
103{
104 async_answer_1(icall, EOK, write_core_files);
105}
106
107static void corecfg_set_enable_srv(ipc_call_t *icall)
108{
109 write_core_files = ipc_get_arg1(icall);
110 async_answer_0(icall, EOK);
111 (void) taskmon_save_cfg(taskmon_cfg_path);
112}
113
114static void corecfg_client_conn(ipc_call_t *icall, void *arg)
115{
116 /* Accept the connection */
117 async_accept_0(icall);
118
119 while (true) {
120 ipc_call_t call;
121 async_get_call(&call);
122 sysarg_t method = ipc_get_imethod(&call);
123
124 if (!method) {
125 /* The other side has hung up */
126 async_answer_0(&call, EOK);
127 return;
128 }
129
130 switch (method) {
131 case CORECFG_GET_ENABLE:
132 corecfg_get_enable_srv(&call);
133 break;
134 case CORECFG_SET_ENABLE:
135 corecfg_set_enable_srv(&call);
136 break;
137 default:
138 async_answer_0(&call, ENOTSUP);
139 }
140 }
141}
142
143/** Load task monitor configuration from SIF file.
144 *
145 * @param cfgpath Configuration file path
146 *
147 * @return EOK on success or an error code
148 */
149static errno_t taskmon_load_cfg(const char *cfgpath)
150{
151 sif_doc_t *doc = NULL;
152 sif_node_t *rnode;
153 sif_node_t *ncorefiles;
154 const char *ntype;
155 const char *swrite;
156 errno_t rc;
157
158 rc = sif_load(cfgpath, &doc);
159 if (rc != EOK)
160 goto error;
161
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) {
166 rc = EIO;
167 goto error;
168 }
169
170 swrite = sif_node_get_attr(ncorefiles, "write");
171 if (swrite == NULL) {
172 rc = EIO;
173 goto error;
174 }
175
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;
180 } else {
181 rc = EIO;
182 goto error;
183 }
184
185 sif_delete(doc);
186 return EOK;
187error:
188 if (doc != NULL)
189 sif_delete(doc);
190 return rc;
191}
192
193/** Save task monitor configuration to SIF file.
194 *
195 * @param cfgpath Configuration file path
196 *
197 * @return EOK on success or an error code
198 */
199static errno_t taskmon_save_cfg(const char *cfgpath)
200{
201 sif_doc_t *doc = NULL;
202 sif_node_t *rnode;
203 sif_node_t *ncorefiles;
204 errno_t rc;
205
206 rc = sif_new(&doc);
207 if (rc != EOK)
208 goto error;
209
210 rnode = sif_get_root(doc);
211 rc = sif_node_append_child(rnode, "corefiles", &ncorefiles);
212 if (rc != EOK)
213 goto error;
214
215 rc = sif_node_set_attr(ncorefiles, "write",
216 write_core_files ? "y" : "n");
217 if (rc != EOK)
218 goto error;
219
220 rc = sif_save(doc, cfgpath);
221 if (rc != EOK)
222 goto error;
223
224 sif_delete(doc);
225 return EOK;
226error:
227 if (doc != NULL)
228 sif_delete(doc);
229 return rc;
230}
231
232int main(int argc, char *argv[])
233{
234 loc_srv_t *srv;
235
236 printf("%s: Task Monitoring Service\n", NAME);
237
238#ifdef CONFIG_WRITE_CORE_FILES
239 write_core_files = true;
240#else
241 write_core_files = false;
242#endif
243 (void) taskmon_load_cfg(taskmon_cfg_path);
244
245 if (async_event_subscribe(EVENT_FAULT, fault_event, NULL) != EOK) {
246 printf("%s: Error registering fault notifications.\n", NAME);
247 return -1;
248 }
249
250 async_set_fallback_port_handler(corecfg_client_conn, NULL);
251
252 errno_t rc = loc_server_register(NAME, &srv);
253 if (rc != EOK) {
254 printf("%s: Failed registering server: %s.\n",
255 NAME, str_error(rc));
256 return -1;
257 }
258
259 service_id_t sid;
260 rc = loc_service_register(srv, SERVICE_NAME_CORECFG,
261 fallback_port_id, &sid);
262 if (rc != EOK) {
263 loc_server_unregister(srv);
264 printf("%s: Failed registering service: %s.\n",
265 NAME, str_error(rc));
266 return -1;
267 }
268
269 task_retval(0);
270 async_manager();
271
272 return 0;
273}
274
275/** @}
276 */
Note: See TracBrowser for help on using the repository browser.