]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_shutdown.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / kern / kern_shutdown.c
1 /*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * File: bsd/kern/kern_shutdown.c
30 *
31 * Copyright (C) 1989, NeXT, Inc.
32 *
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/vm.h>
39 #include <sys/proc_internal.h>
40 #include <sys/user.h>
41 #include <sys/reboot.h>
42 #include <sys/conf.h>
43 #include <sys/vnode_internal.h>
44 #include <sys/file_internal.h>
45 #include <sys/mbuf.h>
46 #include <sys/msgbuf.h>
47 #include <sys/ioctl.h>
48 #include <sys/signal.h>
49 #include <sys/tty.h>
50 #include <kern/task.h>
51 #include <sys/quota.h>
52 #include <vm/vm_kern.h>
53 #include <mach/vm_param.h>
54 #include <sys/filedesc.h>
55 #include <mach/host_priv.h>
56 #include <mach/host_reboot.h>
57
58 #include <security/audit/audit.h>
59
60 #include <kern/sched_prim.h> /* for thread_block() */
61 #include <kern/host.h> /* for host_priv_self() */
62 #include <net/if_var.h> /* for if_down_all() */
63 #include <sys/buf_internal.h> /* for count_busy_buffers() */
64 #include <sys/mount_internal.h> /* for vfs_unmountall() */
65 #include <mach/task.h> /* for task_suspend() */
66 #include <sys/sysproto.h> /* abused for sync() */
67 #include <kern/clock.h> /* for delay_for_interval() */
68 #include <libkern/OSAtomic.h>
69 #include <IOKit/IOPlatformExpert.h>
70 #include <IOKit/IOMessage.h>
71
72 #include <sys/kdebug.h>
73
74 uint32_t system_inshutdown = 0;
75
76 #if XNU_TARGET_OS_OSX
77 /* XXX should be in a header file somewhere, but isn't */
78 extern void (*unmountroot_pre_hook)(void);
79 #endif
80
81 unsigned int proc_shutdown_exitcount = 0;
82
83 static int sd_openlog(vfs_context_t);
84 static int sd_closelog(vfs_context_t);
85 static void sd_log(vfs_context_t, const char *, ...);
86 static void proc_shutdown(int only_non_dext);
87 static void zprint_panic_info(void);
88 extern void halt_log_enter(const char * what, const void * pc, uint64_t time);
89
90 #if DEVELOPMENT || DEBUG
91 extern boolean_t kdp_has_polled_corefile(void);
92 #endif /* DEVELOPMENT || DEBUG */
93
94 struct sd_filterargs {
95 int delayterm;
96 int shutdownstate;
97 int only_non_dext;
98 };
99
100
101 struct sd_iterargs {
102 int signo; /* the signal to be posted */
103 int setsdstate; /* shutdown state to be set */
104 int countproc; /* count processes on action */
105 int activecount; /* number of processes on which action was done */
106 };
107
108 static vnode_t sd_logvp = NULLVP;
109 static off_t sd_log_offset = 0;
110
111
112 static int sd_filt1(proc_t, void *);
113 static int sd_filt2(proc_t, void *);
114 static int sd_callback1(proc_t p, void * arg);
115 static int sd_callback2(proc_t p, void * arg);
116 static int sd_callback3(proc_t p, void * arg);
117
118 extern bool panic_include_zprint;
119 extern mach_memory_info_t *panic_kext_memory_info;
120 extern vm_size_t panic_kext_memory_size;
121
122 static void
123 zprint_panic_info(void)
124 {
125 unsigned int num_sites;
126 kern_return_t kr;
127
128 panic_include_zprint = TRUE;
129 panic_kext_memory_info = NULL;
130 panic_kext_memory_size = 0;
131
132 num_sites = vm_page_diagnose_estimate();
133 panic_kext_memory_size = num_sites * sizeof(panic_kext_memory_info[0]);
134
135 kr = kmem_alloc(kernel_map, (vm_offset_t *)&panic_kext_memory_info, round_page(panic_kext_memory_size), VM_KERN_MEMORY_OSFMK);
136 if (kr != KERN_SUCCESS) {
137 panic_kext_memory_info = NULL;
138 return;
139 }
140
141 vm_page_diagnose(panic_kext_memory_info, num_sites, 0);
142 }
143
144 int
145 get_system_inshutdown()
146 {
147 return system_inshutdown;
148 }
149
150 __abortlike
151 static void
152 panic_kernel(int howto, char *message)
153 {
154 if ((howto & RB_PANIC_ZPRINT) == RB_PANIC_ZPRINT) {
155 zprint_panic_info();
156 }
157 panic("userspace panic: %s", message);
158 }
159
160 extern boolean_t compressor_store_stop_compaction;
161 extern lck_mtx_t vm_swap_data_lock;
162 extern int vm_swapfile_create_thread_running;
163 extern int vm_swapfile_gc_thread_running;
164
165 int
166 reboot_kernel(int howto, char *message)
167 {
168 int hostboot_option = 0;
169 uint64_t startTime;
170
171 if ((howto & (RB_PANIC | RB_QUICK)) == (RB_PANIC | RB_QUICK)) {
172 panic_kernel(howto, message);
173 }
174
175 if (!OSCompareAndSwap(0, 1, &system_inshutdown)) {
176 if ((howto & RB_QUICK) == RB_QUICK) {
177 goto force_reboot;
178 }
179 return EBUSY;
180 }
181
182 lck_mtx_lock(&vm_swap_data_lock);
183
184 /* Turn OFF future swapfile reclaimation / compaction etc.*/
185 compressor_store_stop_compaction = TRUE;
186
187 /* wait for any current swapfile work to end */
188 while (vm_swapfile_create_thread_running || vm_swapfile_gc_thread_running) {
189 assert_wait((event_t)&compressor_store_stop_compaction, THREAD_UNINT);
190
191 lck_mtx_unlock(&vm_swap_data_lock);
192
193 thread_block(THREAD_CONTINUE_NULL);
194
195 lck_mtx_lock(&vm_swap_data_lock);
196 }
197
198 lck_mtx_unlock(&vm_swap_data_lock);
199
200 /*
201 * Notify the power management root domain that the system will shut down.
202 */
203 IOSystemShutdownNotification(kIOSystemShutdownNotificationStageProcessExit);
204
205 if ((howto & RB_QUICK) == RB_QUICK) {
206 printf("Quick reboot...\n");
207 if ((howto & RB_NOSYNC) == 0) {
208 sync((proc_t)NULL, (void *)NULL, (int *)NULL);
209 }
210 } else if ((howto & RB_NOSYNC) == 0) {
211 int iter, nbusy;
212
213 printf("syncing disks... ");
214
215 /*
216 * Release vnodes held by texts before sync.
217 */
218
219 /* handle live procs (deallocate their root and current directories), suspend initproc */
220
221 startTime = mach_absolute_time();
222 proc_shutdown(TRUE);
223 halt_log_enter("proc_shutdown", 0, mach_absolute_time() - startTime);
224
225 #if CONFIG_AUDIT
226 startTime = mach_absolute_time();
227 audit_shutdown();
228 halt_log_enter("audit_shutdown", 0, mach_absolute_time() - startTime);
229 #endif
230
231 #if XNU_TARGET_OS_OSX
232 if (unmountroot_pre_hook != NULL) {
233 unmountroot_pre_hook();
234 }
235 #endif
236
237 startTime = mach_absolute_time();
238 sync((proc_t)NULL, (void *)NULL, (int *)NULL);
239
240 if (kdebug_enable) {
241 startTime = mach_absolute_time();
242 kdbg_dump_trace_to_file("/var/log/shutdown/shutdown.trace");
243 halt_log_enter("shutdown.trace", 0, mach_absolute_time() - startTime);
244 }
245
246 IOSystemShutdownNotification(kIOSystemShutdownNotificationStageRootUnmount);
247
248 /*
249 * Unmount filesystems
250 */
251
252 #if DEVELOPMENT || DEBUG
253 if (!(howto & RB_PANIC) || !kdp_has_polled_corefile())
254 #endif /* DEVELOPMENT || DEBUG */
255 {
256 startTime = mach_absolute_time();
257 vfs_unmountall(TRUE);
258 halt_log_enter("vfs_unmountall", 0, mach_absolute_time() - startTime);
259 }
260
261 IOSystemShutdownNotification(kIOSystemShutdownNotificationTerminateDEXTs);
262
263 startTime = mach_absolute_time();
264 proc_shutdown(FALSE);
265 halt_log_enter("proc_shutdown", 0, mach_absolute_time() - startTime);
266
267 #if DEVELOPMENT || DEBUG
268 if (!(howto & RB_PANIC) || !kdp_has_polled_corefile())
269 #endif /* DEVELOPMENT || DEBUG */
270 {
271 startTime = mach_absolute_time();
272 vfs_unmountall(FALSE);
273 halt_log_enter("vfs_unmountall", 0, mach_absolute_time() - startTime);
274 }
275
276
277
278 /* Wait for the buffer cache to clean remaining dirty buffers */
279 startTime = mach_absolute_time();
280 for (iter = 0; iter < 100; iter++) {
281 nbusy = count_busy_buffers();
282 if (nbusy == 0) {
283 break;
284 }
285 printf("%d ", nbusy);
286 delay_for_interval( 1 * nbusy, 1000 * 1000);
287 }
288 if (nbusy) {
289 printf("giving up\n");
290 } else {
291 printf("done\n");
292 }
293 halt_log_enter("bufferclean", 0, mach_absolute_time() - startTime);
294 }
295 #if NETWORKING
296 /*
297 * Can't just use an splnet() here to disable the network
298 * because that will lock out softints which the disk
299 * drivers depend on to finish DMAs.
300 */
301 startTime = mach_absolute_time();
302 if_down_all();
303 halt_log_enter("if_down_all", 0, mach_absolute_time() - startTime);
304 #endif /* NETWORKING */
305
306 force_reboot:
307
308 if (howto & RB_PANIC) {
309 panic_kernel(howto, message);
310 }
311
312 if (howto & RB_HALT) {
313 hostboot_option = HOST_REBOOT_HALT;
314 }
315
316 if (howto & RB_UPSDELAY) {
317 hostboot_option = HOST_REBOOT_UPSDELAY;
318 }
319
320 host_reboot(host_priv_self(), hostboot_option);
321 /*
322 * should not be reached
323 */
324 return 0;
325 }
326
327 static int
328 sd_openlog(vfs_context_t ctx)
329 {
330 int error = 0;
331 struct timeval tv;
332
333 /* Open shutdown log */
334 if ((error = vnode_open(PROC_SHUTDOWN_LOG, (O_CREAT | FWRITE | O_NOFOLLOW), 0644, 0, &sd_logvp, ctx))) {
335 printf("Failed to open %s: error %d\n", PROC_SHUTDOWN_LOG, error);
336 sd_logvp = NULLVP;
337 return error;
338 }
339
340 vnode_setsize(sd_logvp, (off_t)0, 0, ctx);
341
342 /* Write a little header */
343 microtime(&tv);
344 sd_log(ctx, "Process shutdown log. Current time is %lu (in seconds).\n\n", tv.tv_sec);
345
346 return 0;
347 }
348
349 static int
350 sd_closelog(vfs_context_t ctx)
351 {
352 int error = 0;
353 if (sd_logvp != NULLVP) {
354 VNOP_FSYNC(sd_logvp, MNT_WAIT, ctx);
355 error = vnode_close(sd_logvp, FWRITE, ctx);
356 sd_logvp = NULLVP;
357 }
358
359 return error;
360 }
361
362 static void
363 sd_log(vfs_context_t ctx, const char *fmt, ...)
364 {
365 int resid, log_error, len;
366 char logbuf[100];
367 va_list arglist;
368
369 /* If the log isn't open yet, open it */
370 if (sd_logvp == NULLVP) {
371 if (sd_openlog(ctx) != 0) {
372 /* Couldn't open, we fail out */
373 return;
374 }
375 }
376
377 va_start(arglist, fmt);
378 len = vsnprintf(logbuf, sizeof(logbuf), fmt, arglist);
379 log_error = vn_rdwr(UIO_WRITE, sd_logvp, (caddr_t)logbuf, len, sd_log_offset,
380 UIO_SYSSPACE, IO_UNIT | IO_NOAUTH, vfs_context_ucred(ctx), &resid, vfs_context_proc(ctx));
381 if (log_error == EIO || log_error == 0) {
382 sd_log_offset += (len - resid);
383 }
384
385 va_end(arglist);
386 }
387
388 #define proc_is_driver(p) (task_is_driver((p)->task))
389
390 static int
391 sd_filt1(proc_t p, void * args)
392 {
393 proc_t self = current_proc();
394 struct sd_filterargs * sf = (struct sd_filterargs *)args;
395 int delayterm = sf->delayterm;
396 int shutdownstate = sf->shutdownstate;
397
398 if (sf->only_non_dext && proc_is_driver(p)) {
399 return 0;
400 }
401
402 if (((p->p_flag & P_SYSTEM) != 0) || (p->p_ppid == 0)
403 || (p == self) || (p->p_stat == SZOMB)
404 || (p->p_shutdownstate != shutdownstate)
405 || ((delayterm == 0) && ((p->p_lflag & P_LDELAYTERM) == P_LDELAYTERM))
406 || ((p->p_sigcatch & sigmask(SIGTERM)) == 0)) {
407 return 0;
408 } else {
409 return 1;
410 }
411 }
412
413
414 static int
415 sd_callback1(proc_t p, void * args)
416 {
417 struct sd_iterargs * sd = (struct sd_iterargs *)args;
418 int signo = sd->signo;
419 int setsdstate = sd->setsdstate;
420 int countproc = sd->countproc;
421
422 proc_lock(p);
423 p->p_shutdownstate = (char)setsdstate;
424 if (p->p_stat != SZOMB) {
425 proc_unlock(p);
426 if (countproc != 0) {
427 proc_list_lock();
428 p->p_listflag |= P_LIST_EXITCOUNT;
429 proc_shutdown_exitcount++;
430 proc_list_unlock();
431 }
432 if (proc_is_driver(p)) {
433 printf("lingering dext %s signal(%d)\n", p->p_name, signo);
434 }
435 psignal(p, signo);
436 if (countproc != 0) {
437 sd->activecount++;
438 }
439 } else {
440 proc_unlock(p);
441 }
442
443 return PROC_RETURNED;
444 }
445
446 static int
447 sd_filt2(proc_t p, void * args)
448 {
449 proc_t self = current_proc();
450 struct sd_filterargs * sf = (struct sd_filterargs *)args;
451 int delayterm = sf->delayterm;
452 int shutdownstate = sf->shutdownstate;
453
454 if (sf->only_non_dext && proc_is_driver(p)) {
455 return 0;
456 }
457
458 if (((p->p_flag & P_SYSTEM) != 0) || (p->p_ppid == 0)
459 || (p == self) || (p->p_stat == SZOMB)
460 || (p->p_shutdownstate == shutdownstate)
461 || ((delayterm == 0) && ((p->p_lflag & P_LDELAYTERM) == P_LDELAYTERM))) {
462 return 0;
463 } else {
464 return 1;
465 }
466 }
467
468 static int
469 sd_callback2(proc_t p, void * args)
470 {
471 struct sd_iterargs * sd = (struct sd_iterargs *)args;
472 int signo = sd->signo;
473 int setsdstate = sd->setsdstate;
474 int countproc = sd->countproc;
475
476 proc_lock(p);
477 p->p_shutdownstate = (char)setsdstate;
478 if (p->p_stat != SZOMB) {
479 proc_unlock(p);
480 if (countproc != 0) {
481 proc_list_lock();
482 p->p_listflag |= P_LIST_EXITCOUNT;
483 proc_shutdown_exitcount++;
484 proc_list_unlock();
485 }
486 if (proc_is_driver(p)) {
487 printf("lingering dext %s signal(%d)\n", p->p_name, signo);
488 }
489 psignal(p, signo);
490 if (countproc != 0) {
491 sd->activecount++;
492 }
493 } else {
494 proc_unlock(p);
495 }
496
497 return PROC_RETURNED;
498 }
499
500 static int
501 sd_callback3(proc_t p, void * args)
502 {
503 struct sd_iterargs * sd = (struct sd_iterargs *)args;
504 vfs_context_t ctx = vfs_context_current();
505
506 int setsdstate = sd->setsdstate;
507
508 proc_lock(p);
509 p->p_shutdownstate = (char)setsdstate;
510 if (p->p_stat != SZOMB) {
511 /*
512 * NOTE: following code ignores sig_lock and plays
513 * with exit_thread correctly. This is OK unless we
514 * are a multiprocessor, in which case I do not
515 * understand the sig_lock. This needs to be fixed.
516 * XXX
517 */
518 if (p->exit_thread) { /* someone already doing it */
519 proc_unlock(p);
520 /* give him a chance */
521 thread_block(THREAD_CONTINUE_NULL);
522 } else {
523 p->exit_thread = current_thread();
524 printf(".");
525
526 sd_log(ctx, "%s[%d] had to be forced closed with exit1().\n", p->p_comm, p->p_pid);
527
528 proc_unlock(p);
529 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE,
530 p->p_pid, 0, 1, 0, 0);
531 sd->activecount++;
532 exit1(p, 1, (int *)NULL);
533 }
534 } else {
535 proc_unlock(p);
536 }
537
538 return PROC_RETURNED;
539 }
540
541
542 /*
543 * proc_shutdown()
544 *
545 * Shutdown down proc system (release references to current and root
546 * dirs for each process).
547 *
548 * POSIX modifications:
549 *
550 * For POSIX fcntl() file locking call vno_lockrelease() on
551 * the file to release all of its record locks, if any.
552 */
553
554 static void
555 proc_shutdown(int only_non_dext)
556 {
557 vfs_context_t ctx = vfs_context_current();
558 struct proc *p, *self;
559 int delayterm = 0;
560 struct sd_filterargs sfargs;
561 struct sd_iterargs sdargs;
562 int error = 0;
563 struct timespec ts;
564
565 /*
566 * Kill as many procs as we can. (Except ourself...)
567 */
568 self = (struct proc *)current_proc();
569
570 /*
571 * Signal the init with SIGTERM so that he does not launch
572 * new processes
573 */
574 p = proc_find(1);
575 if (p && p != self) {
576 psignal(p, SIGTERM);
577 }
578 proc_rele(p);
579
580 printf("Killing all processes ");
581
582 sigterm_loop:
583 /*
584 * send SIGTERM to those procs interested in catching one
585 */
586 sfargs.delayterm = delayterm;
587 sfargs.shutdownstate = 0;
588 sfargs.only_non_dext = only_non_dext;
589 sdargs.signo = SIGTERM;
590 sdargs.setsdstate = 1;
591 sdargs.countproc = 1;
592 sdargs.activecount = 0;
593
594 error = 0;
595 /* post a SIGTERM to all that catch SIGTERM and not marked for delay */
596 proc_rebootscan(sd_callback1, (void *)&sdargs, sd_filt1, (void *)&sfargs);
597
598 if (sdargs.activecount != 0 && proc_shutdown_exitcount != 0) {
599 proc_list_lock();
600 if (proc_shutdown_exitcount != 0) {
601 /*
602 * now wait for up to 3 seconds to allow those procs catching SIGTERM
603 * to digest it
604 * as soon as these procs have exited, we'll continue on to the next step
605 */
606 ts.tv_sec = 3;
607 ts.tv_nsec = 0;
608 error = msleep(&proc_shutdown_exitcount, &proc_list_mlock, PWAIT, "shutdownwait", &ts);
609 if (error != 0) {
610 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
611 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
612 p->p_listflag &= ~P_LIST_EXITCOUNT;
613 }
614 }
615 for (p = zombproc.lh_first; p; p = p->p_list.le_next) {
616 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
617 p->p_listflag &= ~P_LIST_EXITCOUNT;
618 }
619 }
620 }
621 }
622 proc_list_unlock();
623 }
624 if (error == ETIMEDOUT) {
625 /*
626 * log the names of the unresponsive tasks
627 */
628
629 proc_list_lock();
630
631 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
632 if (p->p_shutdownstate == 1) {
633 printf("%s[%d]: didn't act on SIGTERM\n", p->p_comm, p->p_pid);
634 sd_log(ctx, "%s[%d]: didn't act on SIGTERM\n", p->p_comm, p->p_pid);
635 }
636 }
637
638 proc_list_unlock();
639 }
640
641 /*
642 * send a SIGKILL to all the procs still hanging around
643 */
644 sfargs.delayterm = delayterm;
645 sfargs.shutdownstate = 2;
646 sdargs.signo = SIGKILL;
647 sdargs.setsdstate = 2;
648 sdargs.countproc = 1;
649 sdargs.activecount = 0;
650
651 /* post a SIGKILL to all that catch SIGTERM and not marked for delay */
652 proc_rebootscan(sd_callback2, (void *)&sdargs, sd_filt2, (void *)&sfargs);
653
654 error = 0;
655
656 if (sdargs.activecount != 0 && proc_shutdown_exitcount != 0) {
657 proc_list_lock();
658 if (proc_shutdown_exitcount != 0) {
659 /*
660 * wait for up to 60 seconds to allow these procs to exit normally
661 *
662 * History: The delay interval was changed from 100 to 200
663 * for NFS requests in particular.
664 */
665 ts.tv_sec = 10;
666 ts.tv_nsec = 0;
667 error = msleep(&proc_shutdown_exitcount, &proc_list_mlock, PWAIT, "shutdownwait", &ts);
668 if (error != 0) {
669 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
670 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
671 p->p_listflag &= ~P_LIST_EXITCOUNT;
672 }
673 }
674 for (p = zombproc.lh_first; p; p = p->p_list.le_next) {
675 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
676 p->p_listflag &= ~P_LIST_EXITCOUNT;
677 }
678 }
679 }
680 }
681 proc_list_unlock();
682 }
683
684 if (error == ETIMEDOUT) {
685 /*
686 * log the names of the unresponsive tasks
687 */
688
689 proc_list_lock();
690
691 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
692 if (p->p_shutdownstate == 2) {
693 printf("%s[%d]: didn't act on SIGKILL\n", p->p_comm, p->p_pid);
694 sd_log(ctx, "%s[%d]: didn't act on SIGKILL\n", p->p_comm, p->p_pid);
695 }
696 }
697
698 proc_list_unlock();
699 }
700
701 /*
702 * if we still have procs that haven't exited, then brute force 'em
703 */
704 sfargs.delayterm = delayterm;
705 sfargs.shutdownstate = 3;
706 sdargs.signo = 0;
707 sdargs.setsdstate = 3;
708 sdargs.countproc = 0;
709 sdargs.activecount = 0;
710
711
712
713 /* post a SIGTERM to all that catch SIGTERM and not marked for delay */
714 proc_rebootscan(sd_callback3, (void *)&sdargs, sd_filt2, (void *)&sfargs);
715 printf("\n");
716
717 /* Now start the termination of processes that are marked for delayed termn */
718 if (delayterm == 0) {
719 delayterm = 1;
720 goto sigterm_loop;
721 }
722
723 sd_closelog(ctx);
724
725 if (only_non_dext) {
726 return;
727 }
728
729 /*
730 * Now that all other processes have been terminated, suspend init
731 */
732 task_suspend_internal(initproc->task);
733
734 /* drop the ref on initproc */
735 proc_rele(initproc);
736 printf("continuing\n");
737 }