blob: 265d80c55715c4baf15a9d85a4b78e00dd405baa [file] [log] [blame]
Sasha Levin4b1adda2011-10-16 21:57:54 +02001#include <sys/epoll.h>
2#include <sys/un.h>
3#include <sys/types.h>
4#include <sys/socket.h>
Sasha Levine1063722012-09-05 10:31:56 +02005#include <dirent.h>
6
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +01007#include "kvm/epoll.h"
Sasha Levine1063722012-09-05 10:31:56 +02008#include "kvm/kvm-ipc.h"
9#include "kvm/rwsem.h"
10#include "kvm/read-write.h"
11#include "kvm/util.h"
12#include "kvm/kvm.h"
13#include "kvm/builtin-debug.h"
14#include "kvm/strbuf.h"
15#include "kvm/kvm-cpu.h"
16#include "kvm/8250-serial.h"
Sasha Levin4b1adda2011-10-16 21:57:54 +020017
Lai Jiangshana9aae6c2011-12-20 17:08:50 +080018struct kvm_ipc_head {
19 u32 type;
20 u32 len;
21};
22
Sasha Levin4b1adda2011-10-16 21:57:54 +020023#define KVM_IPC_MAX_MSGS 16
24
Sasha Levine1063722012-09-05 10:31:56 +020025#define KVM_SOCK_SUFFIX ".sock"
26#define KVM_SOCK_SUFFIX_LEN ((ssize_t)sizeof(KVM_SOCK_SUFFIX) - 1)
27
28extern __thread struct kvm_cpu *current_kvm_cpu;
29static void (*msgs[KVM_IPC_MAX_MSGS])(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
Sasha Levin4b1adda2011-10-16 21:57:54 +020030static DECLARE_RWSEM(msgs_rwlock);
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +010031static int server_fd;
32static struct kvm__epoll epoll;
Sasha Levin4b1adda2011-10-16 21:57:54 +020033
Sasha Levine1063722012-09-05 10:31:56 +020034static int kvm__create_socket(struct kvm *kvm)
35{
36 char full_name[PATH_MAX];
Andre Przywaraa2583db2015-07-17 17:02:09 +010037 int s;
Sasha Levine1063722012-09-05 10:31:56 +020038 struct sockaddr_un local;
39 int len, r;
40
41 /* This usually 108 bytes long */
42 BUILD_BUG_ON(sizeof(local.sun_path) < 32);
43
44 snprintf(full_name, sizeof(full_name), "%s/%s%s",
45 kvm__get_dir(), kvm->cfg.guest_name, KVM_SOCK_SUFFIX);
Sasha Levine1063722012-09-05 10:31:56 +020046
47 s = socket(AF_UNIX, SOCK_STREAM, 0);
Michael Ellerman211370d2013-02-06 19:19:12 +110048 if (s < 0) {
49 perror("socket");
Sasha Levine1063722012-09-05 10:31:56 +020050 return s;
Michael Ellerman211370d2013-02-06 19:19:12 +110051 }
52
Sasha Levine1063722012-09-05 10:31:56 +020053 local.sun_family = AF_UNIX;
54 strlcpy(local.sun_path, full_name, sizeof(local.sun_path));
55 len = strlen(local.sun_path) + sizeof(local.sun_family);
56 r = bind(s, (struct sockaddr *)&local, len);
Andre Przywaraef5b9412019-06-07 18:01:21 +010057 /* Check for an existing socket file */
58 if (r < 0 && errno == EADDRINUSE) {
59 r = connect(s, (struct sockaddr *)&local, len);
60 if (r == 0) {
61 /*
62 * If we could connect, there is already a guest
63 * using this same name. This should not happen
64 * for PID derived names, but could happen for user
65 * provided guest names.
66 */
67 pr_err("Guest socket file %s already exists.",
68 full_name);
69 r = -EEXIST;
70 goto fail;
71 }
72 if (errno == ECONNREFUSED) {
73 /*
74 * This is a ghost socket file, with no-one listening
75 * on the other end. Since kvmtool will only bind
76 * above when creating a new guest, there is no
77 * danger in just removing the file and re-trying.
78 */
79 unlink(full_name);
80 pr_info("Removed ghost socket file \"%s\".", full_name);
81 r = bind(s, (struct sockaddr *)&local, len);
82 }
83 }
Michael Ellerman211370d2013-02-06 19:19:12 +110084 if (r < 0) {
85 perror("bind");
Sasha Levine1063722012-09-05 10:31:56 +020086 goto fail;
Michael Ellerman211370d2013-02-06 19:19:12 +110087 }
Sasha Levine1063722012-09-05 10:31:56 +020088
89 r = listen(s, 5);
Michael Ellerman211370d2013-02-06 19:19:12 +110090 if (r < 0) {
91 perror("listen");
Sasha Levine1063722012-09-05 10:31:56 +020092 goto fail;
Michael Ellerman211370d2013-02-06 19:19:12 +110093 }
Sasha Levine1063722012-09-05 10:31:56 +020094
95 return s;
96
97fail:
98 close(s);
99 return r;
100}
101
102void kvm__remove_socket(const char *name)
103{
104 char full_name[PATH_MAX];
105
106 snprintf(full_name, sizeof(full_name), "%s/%s%s",
107 kvm__get_dir(), name, KVM_SOCK_SUFFIX);
108 unlink(full_name);
109}
110
111int kvm__get_sock_by_instance(const char *name)
112{
113 int s, len, r;
114 char sock_file[PATH_MAX];
115 struct sockaddr_un local;
116
117 snprintf(sock_file, sizeof(sock_file), "%s/%s%s",
118 kvm__get_dir(), name, KVM_SOCK_SUFFIX);
119 s = socket(AF_UNIX, SOCK_STREAM, 0);
120
121 local.sun_family = AF_UNIX;
122 strlcpy(local.sun_path, sock_file, sizeof(local.sun_path));
123 len = strlen(local.sun_path) + sizeof(local.sun_family);
124
Andre Przywarad77bd4f2015-07-17 17:02:14 +0100125 r = connect(s, (struct sockaddr *)&local, len);
Sasha Levine1063722012-09-05 10:31:56 +0200126 if (r < 0 && errno == ECONNREFUSED) {
Andre Przywara67f9f7b2019-06-07 18:01:20 +0100127 /* Clean up the ghost socket file */
128 unlink(local.sun_path);
129 pr_info("Removed ghost socket file \"%s\".", sock_file);
Sasha Levine1063722012-09-05 10:31:56 +0200130 return r;
131 } else if (r < 0) {
132 return r;
133 }
134
135 return s;
136}
137
Milan Kocian22fb13f2013-06-06 23:15:16 +0200138static bool is_socket(const char *base_path, const struct dirent *dent)
139{
140 switch (dent->d_type) {
141 case DT_SOCK:
142 return true;
143
144 case DT_UNKNOWN: {
145 char path[PATH_MAX];
146 struct stat st;
147
148 sprintf(path, "%s/%s", base_path, dent->d_name);
149 if (stat(path, &st))
150 return false;
151
152 return S_ISSOCK(st.st_mode);
153 }
154 default:
155 return false;
156 }
157}
158
Sasha Levine1063722012-09-05 10:31:56 +0200159int kvm__enumerate_instances(int (*callback)(const char *name, int fd))
160{
161 int sock;
162 DIR *dir;
Michal Rosteckid62653e2016-04-17 17:40:10 +0200163 struct dirent *entry;
Sasha Levine1063722012-09-05 10:31:56 +0200164 int ret = 0;
Milan Kocian22fb13f2013-06-06 23:15:16 +0200165 const char *path;
Sasha Levine1063722012-09-05 10:31:56 +0200166
Milan Kocian22fb13f2013-06-06 23:15:16 +0200167 path = kvm__get_dir();
168
169 dir = opendir(path);
Sasha Levine1063722012-09-05 10:31:56 +0200170 if (!dir)
171 return -errno;
172
173 for (;;) {
Michal Rosteckid62653e2016-04-17 17:40:10 +0200174 entry = readdir(dir);
175 if (!entry)
Sasha Levine1063722012-09-05 10:31:56 +0200176 break;
Michal Rosteckid62653e2016-04-17 17:40:10 +0200177 if (is_socket(path, entry)) {
178 ssize_t name_len = strlen(entry->d_name);
Sasha Levine1063722012-09-05 10:31:56 +0200179 char *p;
180
181 if (name_len <= KVM_SOCK_SUFFIX_LEN)
182 continue;
183
Michal Rosteckid62653e2016-04-17 17:40:10 +0200184 p = &entry->d_name[name_len - KVM_SOCK_SUFFIX_LEN];
Sasha Levine1063722012-09-05 10:31:56 +0200185 if (memcmp(KVM_SOCK_SUFFIX, p, KVM_SOCK_SUFFIX_LEN))
186 continue;
187
188 *p = 0;
Michal Rosteckid62653e2016-04-17 17:40:10 +0200189 sock = kvm__get_sock_by_instance(entry->d_name);
Sasha Levine1063722012-09-05 10:31:56 +0200190 if (sock < 0)
191 continue;
Michal Rosteckid62653e2016-04-17 17:40:10 +0200192 ret = callback(entry->d_name, sock);
Sasha Levine1063722012-09-05 10:31:56 +0200193 close(sock);
194 if (ret < 0)
195 break;
196 }
197 }
198
199 closedir(dir);
200
201 return ret;
202}
203
204int kvm_ipc__register_handler(u32 type, void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg))
Sasha Levin4b1adda2011-10-16 21:57:54 +0200205{
206 if (type >= KVM_IPC_MAX_MSGS)
207 return -ENOSPC;
208
209 down_write(&msgs_rwlock);
210 msgs[type] = cb;
211 up_write(&msgs_rwlock);
212
213 return 0;
214}
215
Lai Jiangshan50dc18a2011-12-20 17:08:51 +0800216int kvm_ipc__send(int fd, u32 type)
217{
218 struct kvm_ipc_head head = {.type = type, .len = 0,};
219
Asias Heca088262012-01-09 17:19:26 +0800220 if (write_in_full(fd, &head, sizeof(head)) < 0)
Lai Jiangshan50dc18a2011-12-20 17:08:51 +0800221 return -1;
222
223 return 0;
224}
225
226int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg)
227{
228 struct kvm_ipc_head head = {.type = type, .len = len,};
229
Asias Heca088262012-01-09 17:19:26 +0800230 if (write_in_full(fd, &head, sizeof(head)) < 0)
Lai Jiangshan50dc18a2011-12-20 17:08:51 +0800231 return -1;
232
Asias Hefd5b45a2012-01-09 17:18:01 +0800233 if (write_in_full(fd, msg, len) < 0)
Lai Jiangshan50dc18a2011-12-20 17:08:51 +0800234 return -1;
235
236 return 0;
237}
238
Sasha Levine1063722012-09-05 10:31:56 +0200239static int kvm_ipc__handle(struct kvm *kvm, int fd, u32 type, u32 len, u8 *data)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200240{
Sasha Levine1063722012-09-05 10:31:56 +0200241 void (*cb)(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200242
Lai Jiangshan44a56bf2011-12-20 17:08:49 +0800243 if (type >= KVM_IPC_MAX_MSGS)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200244 return -ENOSPC;
245
246 down_read(&msgs_rwlock);
Lai Jiangshan44a56bf2011-12-20 17:08:49 +0800247 cb = msgs[type];
Sasha Levin4b1adda2011-10-16 21:57:54 +0200248 up_read(&msgs_rwlock);
249
250 if (cb == NULL) {
Lai Jiangshan44a56bf2011-12-20 17:08:49 +0800251 pr_warning("No device handles type %u\n", type);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200252 return -ENODEV;
253 }
254
Sasha Levine1063722012-09-05 10:31:56 +0200255 cb(kvm, fd, type, len, data);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200256
257 return 0;
258}
259
260static int kvm_ipc__new_conn(int fd)
261{
262 int client;
263 struct epoll_event ev;
264
265 client = accept(fd, NULL, NULL);
266 if (client < 0)
267 return -1;
268
269 ev.events = EPOLLIN | EPOLLRDHUP;
270 ev.data.fd = client;
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100271 if (epoll_ctl(epoll.fd, EPOLL_CTL_ADD, client, &ev) < 0) {
Sasha Levin4b1adda2011-10-16 21:57:54 +0200272 close(client);
273 return -1;
274 }
275
276 return client;
277}
278
279static void kvm_ipc__close_conn(int fd)
280{
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100281 epoll_ctl(epoll.fd, EPOLL_CTL_DEL, fd, NULL);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200282 close(fd);
283}
284
Sasha Levine1063722012-09-05 10:31:56 +0200285static int kvm_ipc__receive(struct kvm *kvm, int fd)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200286{
Lai Jiangshana9aae6c2011-12-20 17:08:50 +0800287 struct kvm_ipc_head head;
288 u8 *msg = NULL;
Sasha Levin4b1adda2011-10-16 21:57:54 +0200289 u32 n;
290
Lai Jiangshana9aae6c2011-12-20 17:08:50 +0800291 n = read(fd, &head, sizeof(head));
292 if (n != sizeof(head))
293 goto done;
294
295 msg = malloc(head.len);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200296 if (msg == NULL)
297 goto done;
298
Lai Jiangshana9aae6c2011-12-20 17:08:50 +0800299 n = read_in_full(fd, msg, head.len);
300 if (n != head.len)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200301 goto done;
302
Sasha Levine1063722012-09-05 10:31:56 +0200303 kvm_ipc__handle(kvm, fd, head.type, head.len, msg);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200304
Asias He8e463c62011-12-22 10:10:42 +0800305 return 0;
306
Sasha Levin4b1adda2011-10-16 21:57:54 +0200307done:
308 free(msg);
Asias He8e463c62011-12-22 10:10:42 +0800309 return -1;
Sasha Levin4b1adda2011-10-16 21:57:54 +0200310}
311
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100312static void kvm_ipc__handle_event(struct kvm *kvm, struct epoll_event *ev)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200313{
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100314 int fd = ev->data.fd;
Sasha Levin4b1adda2011-10-16 21:57:54 +0200315
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100316 if (fd == server_fd) {
317 int client, r;
Sasha Levina4d8c552012-10-24 12:52:27 -0400318
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100319 client = kvm_ipc__new_conn(fd);
320 /*
321 * Handle multiple IPC cmd at a time
322 */
323 do {
324 r = kvm_ipc__receive(kvm, client);
325 } while (r == 0);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200326
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100327 } else if (ev->events & (EPOLLERR | EPOLLRDHUP | EPOLLHUP)) {
328 kvm_ipc__close_conn(fd);
329 } else {
330 kvm_ipc__receive(kvm, fd);
Sasha Levin4b1adda2011-10-16 21:57:54 +0200331 }
Sasha Levin4b1adda2011-10-16 21:57:54 +0200332}
333
Sasha Levine1063722012-09-05 10:31:56 +0200334static void kvm__pid(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
335{
336 pid_t pid = getpid();
337 int r = 0;
338
339 if (type == KVM_IPC_PID)
340 r = write(fd, &pid, sizeof(pid));
341
342 if (r < 0)
343 pr_warning("Failed sending PID");
344}
345
346static void handle_stop(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
347{
348 if (WARN_ON(type != KVM_IPC_STOP || len))
349 return;
350
Will Deacon2aa76b22015-11-05 18:33:00 +0000351 kvm__reboot(kvm);
Sasha Levine1063722012-09-05 10:31:56 +0200352}
353
354/* Pause/resume the guest using SIGUSR2 */
355static int is_paused;
356
357static void handle_pause(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
358{
359 if (WARN_ON(len))
360 return;
361
362 if (type == KVM_IPC_RESUME && is_paused) {
363 kvm->vm_state = KVM_VMSTATE_RUNNING;
Sasha Levin4346fd82012-09-17 10:03:32 +0200364 kvm__continue(kvm);
Sasha Levine1063722012-09-05 10:31:56 +0200365 } else if (type == KVM_IPC_PAUSE && !is_paused) {
366 kvm->vm_state = KVM_VMSTATE_PAUSED;
367 ioctl(kvm->vm_fd, KVM_KVMCLOCK_CTRL);
Sasha Levin4346fd82012-09-17 10:03:32 +0200368 kvm__pause(kvm);
Sasha Levine1063722012-09-05 10:31:56 +0200369 } else {
370 return;
371 }
372
373 is_paused = !is_paused;
374}
375
376static void handle_vmstate(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
377{
378 int r = 0;
379
380 if (type == KVM_IPC_VMSTATE)
381 r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
382
383 if (r < 0)
384 pr_warning("Failed sending VMSTATE");
385}
386
387/*
388 * Serialize debug printout so that the output of multiple vcpus does not
389 * get mixed up:
390 */
391static int printout_done;
392
393static void handle_sigusr1(int sig)
394{
395 struct kvm_cpu *cpu = current_kvm_cpu;
396 int fd = kvm_cpu__get_debug_fd();
397
398 if (!cpu || cpu->needs_nmi)
399 return;
400
401 dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
402 kvm_cpu__show_registers(cpu);
403 kvm_cpu__show_code(cpu);
404 kvm_cpu__show_page_tables(cpu);
405 fflush(stdout);
406 printout_done = 1;
407}
408
409static void handle_debug(struct kvm *kvm, int fd, u32 type, u32 len, u8 *msg)
410{
411 int i;
412 struct debug_cmd_params *params;
413 u32 dbg_type;
414 u32 vcpu;
415
416 if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
417 return;
418
419 params = (void *)msg;
420 dbg_type = params->dbg_type;
421 vcpu = params->cpu;
422
423 if (dbg_type & KVM_DEBUG_CMD_TYPE_SYSRQ)
424 serial8250__inject_sysrq(kvm, params->sysrq);
425
426 if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
427 if ((int)vcpu >= kvm->nrcpus)
428 return;
429
430 kvm->cpus[vcpu]->needs_nmi = 1;
431 pthread_kill(kvm->cpus[vcpu]->thread, SIGUSR1);
432 }
433
434 if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
435 return;
436
437 for (i = 0; i < kvm->nrcpus; i++) {
438 struct kvm_cpu *cpu = kvm->cpus[i];
439
440 if (!cpu)
441 continue;
442
443 printout_done = 0;
444
445 kvm_cpu__set_debug_fd(fd);
446 pthread_kill(cpu->thread, SIGUSR1);
447 /*
448 * Wait for the vCPU to dump state before signalling
449 * the next thread. Since this is debug code it does
450 * not matter that we are burning CPU time a bit:
451 */
452 while (!printout_done)
453 sleep(0);
454 }
455
456 close(fd);
457
458 serial8250__inject_sysrq(kvm, 'p');
459}
460
461int kvm_ipc__init(struct kvm *kvm)
Sasha Levin4b1adda2011-10-16 21:57:54 +0200462{
Yang Baie21e8ff2012-02-10 17:55:35 +0800463 int ret;
Sasha Levine1063722012-09-05 10:31:56 +0200464 int sock = kvm__create_socket(kvm);
Sasha Levin21b3c2c2011-12-06 14:15:30 +0200465 struct epoll_event ev = {0};
Sasha Levin4b1adda2011-10-16 21:57:54 +0200466
467 server_fd = sock;
468
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100469 ret = epoll__init(kvm, &epoll, "kvm-ipc",
470 kvm_ipc__handle_event);
471 if (ret) {
472 pr_err("Failed starting IPC thread");
Yang Baie21e8ff2012-02-10 17:55:35 +0800473 goto err;
474 }
Sasha Levin4b1adda2011-10-16 21:57:54 +0200475
Sasha Levin47f72b92011-10-28 11:01:54 +0200476 ev.events = EPOLLIN | EPOLLET;
Sasha Levin4b1adda2011-10-16 21:57:54 +0200477 ev.data.fd = sock;
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100478 if (epoll_ctl(epoll.fd, EPOLL_CTL_ADD, sock, &ev) < 0) {
Michael Ellerman211370d2013-02-06 19:19:12 +1100479 pr_err("Failed adding socket to epoll");
Yang Baie21e8ff2012-02-10 17:55:35 +0800480 ret = -EFAULT;
481 goto err_epoll;
482 }
Sasha Levin4b1adda2011-10-16 21:57:54 +0200483
Sasha Levine1063722012-09-05 10:31:56 +0200484 kvm_ipc__register_handler(KVM_IPC_PID, kvm__pid);
485 kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
486 kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
487 kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
488 kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
489 kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
490 signal(SIGUSR1, handle_sigusr1);
491
Sasha Levin4b1adda2011-10-16 21:57:54 +0200492 return 0;
Yang Baie21e8ff2012-02-10 17:55:35 +0800493
Yang Baie21e8ff2012-02-10 17:55:35 +0800494err_epoll:
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100495 epoll__exit(&epoll);
496 close(server_fd);
Yang Baie21e8ff2012-02-10 17:55:35 +0800497err:
498 return ret;
Sasha Levin4b1adda2011-10-16 21:57:54 +0200499}
Sasha Levin49a8afd2012-09-17 10:03:30 +0200500base_init(kvm_ipc__init);
Sasha Levinc733c802011-10-25 13:30:53 +0200501
Sasha Levine1063722012-09-05 10:31:56 +0200502int kvm_ipc__exit(struct kvm *kvm)
Sasha Levinc733c802011-10-25 13:30:53 +0200503{
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100504 epoll__exit(&epoll);
Sasha Levinc733c802011-10-25 13:30:53 +0200505 close(server_fd);
Sasha Levinc733c802011-10-25 13:30:53 +0200506
Sasha Levine1063722012-09-05 10:31:56 +0200507 kvm__remove_socket(kvm->cfg.guest_name);
508
Jean-Philippe Bruckerd30d9482023-06-06 14:04:24 +0100509 return 0;
Sasha Levinc733c802011-10-25 13:30:53 +0200510}
Sasha Levin49a8afd2012-09-17 10:03:30 +0200511base_exit(kvm_ipc__exit);