]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_shutdown.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / kern / kern_shutdown.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
91447636 39#include <sys/proc_internal.h>
1c79356b 40#include <sys/user.h>
1c79356b
A
41#include <sys/reboot.h>
42#include <sys/conf.h>
91447636
A
43#include <sys/vnode_internal.h>
44#include <sys/file_internal.h>
1c79356b
A
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>
9bccf70c 51#include <sys/quota.h>
1c79356b
A
52#include <vm/vm_kern.h>
53#include <mach/vm_param.h>
54#include <sys/filedesc.h>
91447636 55#include <mach/host_priv.h>
1c79356b 56#include <mach/host_reboot.h>
91447636 57
b0d623f7 58#include <security/audit/audit.h>
1c79356b 59
0a7de745
A
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() */
6d2010ae 68#include <libkern/OSAtomic.h>
a39ff7e2 69#include <IOKit/IOPlatformExpert.h>
c3c9b80d 70#include <IOKit/IOMessage.h>
2d21ac55 71
b0d623f7
A
72#include <sys/kdebug.h>
73
6d2010ae 74uint32_t system_inshutdown = 0;
b0d623f7 75
f427ee49 76#if XNU_TARGET_OS_OSX
2d21ac55 77/* XXX should be in a header file somewhere, but isn't */
b0d623f7 78extern void (*unmountroot_pre_hook)(void);
f427ee49 79#endif
2d21ac55 80
b0d623f7 81unsigned int proc_shutdown_exitcount = 0;
2d21ac55 82
b0d623f7
A
83static int sd_openlog(vfs_context_t);
84static int sd_closelog(vfs_context_t);
85static void sd_log(vfs_context_t, const char *, ...);
c3c9b80d 86static void proc_shutdown(int only_non_dext);
d26ffc64 87static void zprint_panic_info(void);
5ba3f43e
A
88extern void halt_log_enter(const char * what, const void * pc, uint64_t time);
89
490019cf
A
90#if DEVELOPMENT || DEBUG
91extern boolean_t kdp_has_polled_corefile(void);
92#endif /* DEVELOPMENT || DEBUG */
2d21ac55 93
0a7de745 94struct sd_filterargs {
2d21ac55
A
95 int delayterm;
96 int shutdownstate;
c3c9b80d 97 int only_non_dext;
2d21ac55
A
98};
99
100
101struct sd_iterargs {
0a7de745
A
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 */
2d21ac55
A
106};
107
b0d623f7
A
108static vnode_t sd_logvp = NULLVP;
109static off_t sd_log_offset = 0;
110
111
2d21ac55
A
112static int sd_filt1(proc_t, void *);
113static int sd_filt2(proc_t, void *);
39037602
A
114static int sd_callback1(proc_t p, void * arg);
115static int sd_callback2(proc_t p, void * arg);
116static int sd_callback3(proc_t p, void * arg);
1c79356b 117
c3c9b80d 118extern bool panic_include_zprint;
5ba3f43e
A
119extern mach_memory_info_t *panic_kext_memory_info;
120extern vm_size_t panic_kext_memory_size;
3e170ce0
A
121
122static void
d26ffc64 123zprint_panic_info(void)
3e170ce0 124{
5ba3f43e
A
125 unsigned int num_sites;
126 kern_return_t kr;
3e170ce0
A
127
128 panic_include_zprint = TRUE;
5ba3f43e 129 panic_kext_memory_info = NULL;
3e170ce0
A
130 panic_kext_memory_size = 0;
131
5ba3f43e
A
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);
3e170ce0 136 if (kr != KERN_SUCCESS) {
5ba3f43e 137 panic_kext_memory_info = NULL;
3e170ce0
A
138 return;
139 }
5ba3f43e
A
140
141 vm_page_diagnose(panic_kext_memory_info, num_sites, 0);
3e170ce0
A
142}
143
813fb2f6
A
144int
145get_system_inshutdown()
146{
0a7de745 147 return system_inshutdown;
813fb2f6
A
148}
149
cb323159 150__abortlike
d26ffc64
A
151static void
152panic_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
cb323159
A
160extern boolean_t compressor_store_stop_compaction;
161extern lck_mtx_t vm_swap_data_lock;
162extern int vm_swapfile_create_thread_running;
163extern int vm_swapfile_gc_thread_running;
164
6d2010ae 165int
3e170ce0 166reboot_kernel(int howto, char *message)
1c79356b 167{
0a7de745 168 int hostboot_option = 0;
5ba3f43e 169 uint64_t startTime;
1c79356b 170
d26ffc64
A
171 if ((howto & (RB_PANIC | RB_QUICK)) == (RB_PANIC | RB_QUICK)) {
172 panic_kernel(howto, message);
173 }
174
6d2010ae 175 if (!OSCompareAndSwap(0, 1, &system_inshutdown)) {
0a7de745 176 if ((howto & RB_QUICK) == RB_QUICK) {
6d2010ae 177 goto force_reboot;
0a7de745
A
178 }
179 return EBUSY;
6d2010ae 180 }
cb323159
A
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
6d2010ae 200 /*
a39ff7e2 201 * Notify the power management root domain that the system will shut down.
6d2010ae 202 */
a39ff7e2 203 IOSystemShutdownNotification(kIOSystemShutdownNotificationStageProcessExit);
2d21ac55 204
0a7de745 205 if ((howto & RB_QUICK) == RB_QUICK) {
b0d623f7 206 printf("Quick reboot...\n");
0a7de745 207 if ((howto & RB_NOSYNC) == 0) {
3e170ce0 208 sync((proc_t)NULL, (void *)NULL, (int *)NULL);
b0d623f7 209 }
0a7de745 210 } else if ((howto & RB_NOSYNC) == 0) {
1c79356b
A
211 int iter, nbusy;
212
1c79356b
A
213 printf("syncing disks... ");
214
215 /*
216 * Release vnodes held by texts before sync.
217 */
218
3e170ce0 219 /* handle live procs (deallocate their root and current directories), suspend initproc */
5ba3f43e
A
220
221 startTime = mach_absolute_time();
c3c9b80d 222 proc_shutdown(TRUE);
5ba3f43e 223 halt_log_enter("proc_shutdown", 0, mach_absolute_time() - startTime);
1c79356b 224
b0d623f7 225#if CONFIG_AUDIT
5ba3f43e 226 startTime = mach_absolute_time();
6d2010ae 227 audit_shutdown();
5ba3f43e 228 halt_log_enter("audit_shutdown", 0, mach_absolute_time() - startTime);
2d21ac55 229#endif
55e303ae 230
f427ee49 231#if XNU_TARGET_OS_OSX
0a7de745 232 if (unmountroot_pre_hook != NULL) {
b0d623f7 233 unmountroot_pre_hook();
0a7de745 234 }
f427ee49 235#endif
b0d623f7 236
5ba3f43e 237 startTime = mach_absolute_time();
3e170ce0 238 sync((proc_t)NULL, (void *)NULL, (int *)NULL);
1c79356b 239
5ba3f43e
A
240 if (kdebug_enable) {
241 startTime = mach_absolute_time();
b0d623f7 242 kdbg_dump_trace_to_file("/var/log/shutdown/shutdown.trace");
5ba3f43e
A
243 halt_log_enter("shutdown.trace", 0, mach_absolute_time() - startTime);
244 }
b0d623f7 245
a39ff7e2
A
246 IOSystemShutdownNotification(kIOSystemShutdownNotificationStageRootUnmount);
247
1c79356b
A
248 /*
249 * Unmount filesystems
250 */
490019cf
A
251
252#if DEVELOPMENT || DEBUG
253 if (!(howto & RB_PANIC) || !kdp_has_polled_corefile())
254#endif /* DEVELOPMENT || DEBUG */
255 {
5ba3f43e 256 startTime = mach_absolute_time();
c3c9b80d 257 vfs_unmountall(TRUE);
5ba3f43e 258 halt_log_enter("vfs_unmountall", 0, mach_absolute_time() - startTime);
490019cf 259 }
1c79356b 260
c3c9b80d
A
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
1c79356b 278 /* Wait for the buffer cache to clean remaining dirty buffers */
5ba3f43e 279 startTime = mach_absolute_time();
91447636 280 for (iter = 0; iter < 100; iter++) {
1c79356b 281 nbusy = count_busy_buffers();
0a7de745 282 if (nbusy == 0) {
1c79356b 283 break;
0a7de745 284 }
1c79356b 285 printf("%d ", nbusy);
2d21ac55 286 delay_for_interval( 1 * nbusy, 1000 * 1000);
1c79356b 287 }
0a7de745 288 if (nbusy) {
1c79356b 289 printf("giving up\n");
0a7de745 290 } else {
1c79356b 291 printf("done\n");
0a7de745 292 }
5ba3f43e 293 halt_log_enter("bufferclean", 0, mach_absolute_time() - startTime);
1c79356b 294 }
2d21ac55 295#if NETWORKING
1c79356b
A
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 */
5ba3f43e 301 startTime = mach_absolute_time();
1c79356b 302 if_down_all();
5ba3f43e 303 halt_log_enter("if_down_all", 0, mach_absolute_time() - startTime);
2d21ac55 304#endif /* NETWORKING */
1c79356b 305
6d2010ae 306force_reboot:
3e170ce0
A
307
308 if (howto & RB_PANIC) {
d26ffc64 309 panic_kernel(howto, message);
3e170ce0
A
310 }
311
0a7de745 312 if (howto & RB_HALT) {
1c79356b 313 hostboot_option = HOST_REBOOT_HALT;
0a7de745 314 }
1c79356b 315
6d2010ae
A
316 if (howto & RB_UPSDELAY) {
317 hostboot_option = HOST_REBOOT_UPSDELAY;
318 }
0c530ab8 319
1c79356b 320 host_reboot(host_priv_self(), hostboot_option);
6d2010ae
A
321 /*
322 * should not be reached
323 */
0a7de745 324 return 0;
1c79356b
A
325}
326
b0d623f7
A
327static int
328sd_openlog(vfs_context_t ctx)
329{
330 int error = 0;
331 struct timeval tv;
0a7de745 332
b0d623f7
A
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
349static int
350sd_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);
c3c9b80d 356 sd_logvp = NULLVP;
b0d623f7
A
357 }
358
359 return error;
360}
361
362static void
0a7de745 363sd_log(vfs_context_t ctx, const char *fmt, ...)
b0d623f7
A
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,
0a7de745 380 UIO_SYSSPACE, IO_UNIT | IO_NOAUTH, vfs_context_ucred(ctx), &resid, vfs_context_proc(ctx));
b0d623f7
A
381 if (log_error == EIO || log_error == 0) {
382 sd_log_offset += (len - resid);
383 }
384
385 va_end(arglist);
b0d623f7
A
386}
387
c3c9b80d
A
388#define proc_is_driver(p) (task_is_driver((p)->task))
389
2d21ac55
A
390static int
391sd_filt1(proc_t p, void * args)
392{
393 proc_t self = current_proc();
394 struct sd_filterargs * sf = (struct sd_filterargs *)args;
0a7de745 395 int delayterm = sf->delayterm;
2d21ac55
A
396 int shutdownstate = sf->shutdownstate;
397
c3c9b80d
A
398 if (sf->only_non_dext && proc_is_driver(p)) {
399 return 0;
400 }
401
0a7de745
A
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 }
2d21ac55
A
411}
412
413
39037602 414static int
2d21ac55
A
415sd_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;
b0d623f7 420 int countproc = sd->countproc;
2d21ac55
A
421
422 proc_lock(p);
f427ee49 423 p->p_shutdownstate = (char)setsdstate;
2d21ac55
A
424 if (p->p_stat != SZOMB) {
425 proc_unlock(p);
b0d623f7
A
426 if (countproc != 0) {
427 proc_list_lock();
428 p->p_listflag |= P_LIST_EXITCOUNT;
429 proc_shutdown_exitcount++;
430 proc_list_unlock();
431 }
c3c9b80d
A
432 if (proc_is_driver(p)) {
433 printf("lingering dext %s signal(%d)\n", p->p_name, signo);
434 }
2d21ac55 435 psignal(p, signo);
0a7de745 436 if (countproc != 0) {
b0d623f7 437 sd->activecount++;
0a7de745 438 }
39037602 439 } else {
2d21ac55 440 proc_unlock(p);
39037602
A
441 }
442
443 return PROC_RETURNED;
2d21ac55
A
444}
445
446static int
447sd_filt2(proc_t p, void * args)
448{
449 proc_t self = current_proc();
450 struct sd_filterargs * sf = (struct sd_filterargs *)args;
0a7de745 451 int delayterm = sf->delayterm;
2d21ac55
A
452 int shutdownstate = sf->shutdownstate;
453
c3c9b80d
A
454 if (sf->only_non_dext && proc_is_driver(p)) {
455 return 0;
456 }
457
0a7de745
A
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 }
2d21ac55
A
466}
467
39037602 468static int
2d21ac55
A
469sd_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;
b0d623f7 474 int countproc = sd->countproc;
2d21ac55
A
475
476 proc_lock(p);
f427ee49 477 p->p_shutdownstate = (char)setsdstate;
2d21ac55
A
478 if (p->p_stat != SZOMB) {
479 proc_unlock(p);
0a7de745 480 if (countproc != 0) {
b0d623f7
A
481 proc_list_lock();
482 p->p_listflag |= P_LIST_EXITCOUNT;
483 proc_shutdown_exitcount++;
484 proc_list_unlock();
485 }
c3c9b80d
A
486 if (proc_is_driver(p)) {
487 printf("lingering dext %s signal(%d)\n", p->p_name, signo);
488 }
2d21ac55 489 psignal(p, signo);
0a7de745 490 if (countproc != 0) {
b0d623f7 491 sd->activecount++;
0a7de745 492 }
39037602 493 } else {
2d21ac55 494 proc_unlock(p);
39037602 495 }
2d21ac55 496
39037602 497 return PROC_RETURNED;
2d21ac55
A
498}
499
39037602 500static int
2d21ac55
A
501sd_callback3(proc_t p, void * args)
502{
503 struct sd_iterargs * sd = (struct sd_iterargs *)args;
b0d623f7
A
504 vfs_context_t ctx = vfs_context_current();
505
2d21ac55
A
506 int setsdstate = sd->setsdstate;
507
508 proc_lock(p);
f427ee49 509 p->p_shutdownstate = (char)setsdstate;
2d21ac55 510 if (p->p_stat != SZOMB) {
0a7de745
A
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 */
2d21ac55
A
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(".");
b0d623f7
A
525
526 sd_log(ctx, "%s[%d] had to be forced closed with exit1().\n", p->p_comm, p->p_pid);
527
2d21ac55 528 proc_unlock(p);
b0d623f7 529 KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_PROC, BSD_PROC_FRCEXIT) | DBG_FUNC_NONE,
0a7de745 530 p->p_pid, 0, 1, 0, 0);
b0d623f7 531 sd->activecount++;
2d21ac55
A
532 exit1(p, 1, (int *)NULL);
533 }
39037602 534 } else {
2d21ac55 535 proc_unlock(p);
39037602 536 }
2d21ac55 537
39037602 538 return PROC_RETURNED;
2d21ac55
A
539}
540
541
1c79356b
A
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 *
5ba3f43e 550 * For POSIX fcntl() file locking call vno_lockrelease() on
1c79356b
A
551 * the file to release all of its record locks, if any.
552 */
553
554static void
c3c9b80d 555proc_shutdown(int only_non_dext)
1c79356b 556{
b0d623f7
A
557 vfs_context_t ctx = vfs_context_current();
558 struct proc *p, *self;
91447636 559 int delayterm = 0;
2d21ac55
A
560 struct sd_filterargs sfargs;
561 struct sd_iterargs sdargs;
b0d623f7
A
562 int error = 0;
563 struct timespec ts;
1c79356b
A
564
565 /*
566 * Kill as many procs as we can. (Except ourself...)
567 */
0b4e3aa0 568 self = (struct proc *)current_proc();
5ba3f43e 569
1c79356b 570 /*
91447636 571 * Signal the init with SIGTERM so that he does not launch
5ba3f43e 572 * new processes
1c79356b 573 */
2d21ac55 574 p = proc_find(1);
91447636
A
575 if (p && p != self) {
576 psignal(p, SIGTERM);
577 }
2d21ac55 578 proc_rele(p);
1c79356b 579
1c79356b
A
580 printf("Killing all processes ");
581
2d21ac55 582sigterm_loop:
1c79356b
A
583 /*
584 * send SIGTERM to those procs interested in catching one
585 */
2d21ac55
A
586 sfargs.delayterm = delayterm;
587 sfargs.shutdownstate = 0;
c3c9b80d 588 sfargs.only_non_dext = only_non_dext;
2d21ac55
A
589 sdargs.signo = SIGTERM;
590 sdargs.setsdstate = 1;
b0d623f7
A
591 sdargs.countproc = 1;
592 sdargs.activecount = 0;
2d21ac55 593
b0d623f7 594 error = 0;
2d21ac55
A
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);
91447636 597
0a7de745 598 if (sdargs.activecount != 0 && proc_shutdown_exitcount != 0) {
2d21ac55 599 proc_list_lock();
b0d623f7
A
600 if (proc_shutdown_exitcount != 0) {
601 /*
5ba3f43e
A
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;
b0d623f7 607 ts.tv_nsec = 0;
c3c9b80d 608 error = msleep(&proc_shutdown_exitcount, &proc_list_mlock, PWAIT, "shutdownwait", &ts);
b0d623f7
A
609 if (error != 0) {
610 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
0a7de745 611 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
b0d623f7 612 p->p_listflag &= ~P_LIST_EXITCOUNT;
0a7de745 613 }
b0d623f7
A
614 }
615 for (p = zombproc.lh_first; p; p = p->p_list.le_next) {
0a7de745 616 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
b0d623f7 617 p->p_listflag &= ~P_LIST_EXITCOUNT;
0a7de745 618 }
b0d623f7 619 }
91447636 620 }
1c79356b 621 }
2d21ac55 622 proc_list_unlock();
1c79356b 623 }
b0d623f7 624 if (error == ETIMEDOUT) {
91447636 625 /*
55e303ae
A
626 * log the names of the unresponsive tasks
627 */
91447636 628
2d21ac55
A
629 proc_list_lock();
630
b0d623f7 631 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
91447636 632 if (p->p_shutdownstate == 1) {
b0d623f7
A
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);
91447636 635 }
55e303ae 636 }
2d21ac55
A
637
638 proc_list_unlock();
55e303ae 639 }
1c79356b
A
640
641 /*
642 * send a SIGKILL to all the procs still hanging around
643 */
2d21ac55
A
644 sfargs.delayterm = delayterm;
645 sfargs.shutdownstate = 2;
646 sdargs.signo = SIGKILL;
647 sdargs.setsdstate = 2;
b0d623f7
A
648 sdargs.countproc = 1;
649 sdargs.activecount = 0;
2d21ac55 650
b0d623f7 651 /* post a SIGKILL to all that catch SIGTERM and not marked for delay */
2d21ac55 652 proc_rebootscan(sd_callback2, (void *)&sdargs, sd_filt2, (void *)&sfargs);
91447636 653
5ba3f43e
A
654 error = 0;
655
0a7de745 656 if (sdargs.activecount != 0 && proc_shutdown_exitcount != 0) {
2d21ac55 657 proc_list_lock();
b0d623f7
A
658 if (proc_shutdown_exitcount != 0) {
659 /*
0a7de745
A
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 */
5ba3f43e 665 ts.tv_sec = 10;
b0d623f7 666 ts.tv_nsec = 0;
c3c9b80d 667 error = msleep(&proc_shutdown_exitcount, &proc_list_mlock, PWAIT, "shutdownwait", &ts);
b0d623f7
A
668 if (error != 0) {
669 for (p = allproc.lh_first; p; p = p->p_list.le_next) {
0a7de745 670 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
b0d623f7 671 p->p_listflag &= ~P_LIST_EXITCOUNT;
0a7de745 672 }
b0d623f7
A
673 }
674 for (p = zombproc.lh_first; p; p = p->p_list.le_next) {
0a7de745 675 if ((p->p_listflag & P_LIST_EXITCOUNT) == P_LIST_EXITCOUNT) {
b0d623f7 676 p->p_listflag &= ~P_LIST_EXITCOUNT;
0a7de745 677 }
b0d623f7
A
678 }
679 }
1c79356b 680 }
2d21ac55 681 proc_list_unlock();
1c79356b
A
682 }
683
5ba3f43e
A
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
1c79356b
A
701 /*
702 * if we still have procs that haven't exited, then brute force 'em
703 */
2d21ac55
A
704 sfargs.delayterm = delayterm;
705 sfargs.shutdownstate = 3;
706 sdargs.signo = 0;
707 sdargs.setsdstate = 3;
b0d623f7
A
708 sdargs.countproc = 0;
709 sdargs.activecount = 0;
4a249263 710
5ba3f43e
A
711
712
2d21ac55
A
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");
91447636
A
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;
1c79356b 721 }
b0d623f7
A
722
723 sd_closelog(ctx);
724
c3c9b80d
A
725 if (only_non_dext) {
726 return;
727 }
728
3e170ce0
A
729 /*
730 * Now that all other processes have been terminated, suspend init
731 */
732 task_suspend_internal(initproc->task);
733
2d21ac55
A
734 /* drop the ref on initproc */
735 proc_rele(initproc);
1c79356b
A
736 printf("continuing\n");
737}