1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include <zircon/syscalls.h>
10 #include <task-utils/walker.h>
11
12 typedef struct {
13 zx_koid_t task_id;
14 zx_signals_t clear_mask;
15 zx_signals_t set_mask;
16 } signal_target_t;
17
callback(void * ctx,int depth,zx_handle_t process,zx_koid_t koid,zx_koid_t parent_koid)18 static zx_status_t callback(void* ctx, int depth, zx_handle_t process,
19 zx_koid_t koid, zx_koid_t parent_koid) {
20 signal_target_t* sigt = (signal_target_t*)ctx;
21 if (koid == sigt->task_id) {
22 zx_status_t status = zx_object_signal(process, sigt->clear_mask, sigt->set_mask);
23 if (status == ZX_OK) {
24 printf("signalled process %ld\n", sigt->task_id);
25 } else {
26 printf("something wrong with signalling process %ld, status: %d\n", sigt->task_id, status);
27 }
28 // found and signaled the task - abort the search
29 return ZX_ERR_STOP;
30 }
31 return ZX_OK;
32 }
33
usage(const char * progname)34 static void usage(const char* progname) {
35 fprintf(stderr, "usage: %s <task id> signal-number <set|clear>\n", progname);
36 fprintf(stderr, "signal number is in the range [0-7] and refers to ZX_USER_SIGNAL_[0-7] bits\n");
37 fprintf(stderr, "set|clear indicates wether the signal is added to the set_mask (set) or to the clear_mask (clear)\n");
38 }
39
main(int argc,const char ** argv)40 int main(int argc, const char** argv) {
41 if (argc < 4) {
42 usage(argv[0]);
43 return -1;
44 }
45
46 char* endptr;
47 zx_koid_t task_id = strtol(argv[1], &endptr, 10);
48 if (*endptr != '\0') {
49 fprintf(stderr, "\"%s\" is not a valid task id\n", argv[1]);
50 return -1;
51 }
52
53 long signal = strtol(argv[2], &endptr, 10);
54 if (*endptr != '\0' || signal < 0 || signal > 7) {
55 fprintf(stderr, "\"%s\" is not a valid signal number\n", argv[2]);
56 usage(argv[0]);
57 return -1;
58 }
59
60 static const zx_signals_t user_signal[8] = {
61 ZX_USER_SIGNAL_0,
62 ZX_USER_SIGNAL_1,
63 ZX_USER_SIGNAL_2,
64 ZX_USER_SIGNAL_3,
65 ZX_USER_SIGNAL_4,
66 ZX_USER_SIGNAL_5,
67 ZX_USER_SIGNAL_6,
68 ZX_USER_SIGNAL_7
69 };
70
71 bool is_up;
72 if (strcmp(argv[3], "set") == 0) {
73 is_up = true;
74 } else if (strcmp(argv[3], "clear") == 0) {
75 is_up = false;
76 } else {
77 usage(argv[0]);
78 return -1;
79 }
80
81 signal_target_t sigt = {
82 .task_id = task_id,
83 .clear_mask = is_up ? 0 : user_signal[signal],
84 .set_mask = is_up ? user_signal[signal] : 0
85 };
86
87 zx_status_t status = walk_root_job_tree(callback, callback, NULL, &sigt);
88 if (status == ZX_OK) {
89 fprintf(stderr, "task %lu not found\n", task_id);
90 return -1;
91 }
92
93 return 0;
94 }
95