xref: /dragonfly/usr.bin/dsynth/build.c (revision 1bc877a0)
1 /*
2  * Copyright (c) 2019 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  *
7  * This code uses concepts and configuration based on 'synth', by
8  * John R. Marino <draco@marino.st>, which was written in ada.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  * 3. Neither the name of The DragonFly Project nor the names of its
21  *    contributors may be used to endorse or promote products derived
22  *    from this software without specific, prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
28  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include "dsynth.h"
38 
39 worker_t WorkerAry[MAXWORKERS];
40 int BuildInitialized;
41 int RunningWorkers;
42 int DynamicMaxWorkers;
43 int FailedWorkers;
44 long RunningPkgDepSize;
45 pthread_mutex_t WorkerMutex;
46 pthread_cond_t WorkerCond;
47 
48 static int build_find_leaves(pkg_t *parent, pkg_t *pkg,
49 			pkg_t ***build_tailp, int *app, int *hasworkp,
50 			int depth, int first, int first_one_only);
51 static int buildCalculateDepiDepth(pkg_t *pkg);
52 static void build_clear_trav(pkg_t *pkg);
53 static void startbuild(pkg_t **build_listp, pkg_t ***build_tailp);
54 static int qsort_depi(const void *pkg1, const void *pkg2);
55 static int qsort_idep(const void *pkg1, const void *pkg2);
56 static void startworker(pkg_t *pkg, worker_t *work);
57 static void cleanworker(worker_t *work);
58 static void waitbuild(int whilematch, int dynamicmax);
59 static void workercomplete(worker_t *work);
60 static void *childBuilderThread(void *arg);
61 static int childInstallPkgDeps(worker_t *work);
62 static size_t childInstallPkgDeps_recurse(FILE *fp, pkglink_t *list,
63 			int undoit, int depth, int first_one_only);
64 static void dophase(worker_t *work, wmsg_t *wmsg,
65 			int wdog, int phaseid, const char *phase);
66 static void phaseReapAll(void);
67 static void phaseTerminateSignal(int sig);
68 static char *buildskipreason(pkglink_t *parent, pkg_t *pkg);
69 static int buildskipcount_dueto(pkg_t *pkg, int mode);
70 static int mptylogpoll(int ptyfd, int fdlog, wmsg_t *wmsg,
71 			time_t *wdog_timep);
72 static void doHook(pkg_t *pkg, const char *id, const char *path, int waitfor);
73 static void childHookRun(bulk_t *bulk);
74 static void adjloadavg(double *dload);
75 
76 static worker_t *SigWork;
77 static int MasterPtyFd = -1;
78 static int CopyFileFd = -1;
79 static pid_t SigPid;
80 static const char *WorkerFlavorPrt = "";	/* "" or "@flavor" */
81 
82 #define MPTY_FAILED	-2
83 #define MPTY_AGAIN	-1
84 #define MPTY_EOF	0
85 #define MPTY_DATA	1
86 
87 int BuildTotal;
88 int BuildCount;
89 int BuildSkipCount;
90 int BuildIgnoreCount;
91 int BuildFailCount;
92 int BuildSuccessCount;
93 
94 /*
95  * Initialize the WorkerAry[]
96  */
97 void
98 DoInitBuild(int slot_override)
99 {
100 	worker_t *work;
101 	struct stat st;
102 	int i;
103 
104 	ddassert(slot_override < 0 || MaxWorkers == 1);
105 
106 	bzero(WorkerAry, MaxWorkers * sizeof(worker_t));
107 	pthread_mutex_init(&WorkerMutex, NULL);
108 
109 	for (i = 0; i < MaxWorkers; ++i) {
110 		work = &WorkerAry[i];
111 		work->index = (slot_override >= 0) ? slot_override : i;
112 		work->state = WORKER_NONE;
113 		asprintf(&work->basedir, "%s/SL%02d", BuildBase, work->index);
114 		pthread_cond_init(&work->cond, NULL);
115 	}
116 	BuildCount = 0;
117 
118 	/*
119 	 * Create required sub-directories. The base directories must already
120 	 * exist as a dsynth configuration safety.
121 	 */
122 	if (stat(RepositoryPath, &st) < 0) {
123 		if (mkdir(RepositoryPath, 0755) < 0)
124 			dfatal("Cannot mkdir %s\n", RepositoryPath);
125 	}
126 
127 	BuildInitialized = 1;
128 
129 	/*
130 	 * slow-start (increases at a rate of 1 per 5 seconds)
131 	 */
132 	if (SlowStartOpt > MaxWorkers)
133 		DynamicMaxWorkers = MaxWorkers;
134 	else if (SlowStartOpt > 0)
135 		DynamicMaxWorkers = SlowStartOpt;
136 	else
137 		DynamicMaxWorkers = MaxWorkers;
138 }
139 
140 /*
141  * Called by the frontend to clean-up any hanging mounts.
142  */
143 void
144 DoCleanBuild(int resetlogs)
145 {
146 	int i;
147 
148 	ddassert(BuildInitialized);
149 
150 	if (resetlogs)
151 		dlogreset();
152 	for (i = 0; i < MaxWorkers; ++i) {
153 		DoWorkerUnmounts(&WorkerAry[i]);
154 	}
155 }
156 
157 void
158 DoBuild(pkg_t *pkgs)
159 {
160 	pkg_t *build_list = NULL;
161 	pkg_t **build_tail = &build_list;
162 	pkg_t *scan;
163 	bulk_t *bulk;
164 	int haswork = 1;
165 	int first = 1;
166 	int newtemplate;
167 	time_t startTime;
168 	time_t t;
169 	int h, m, s;
170 
171 	/*
172 	 * We use our bulk system to run hooks.  This will be for
173 	 * Skipped and Ignored.  Success and Failure are handled by
174 	 * WorkerProcess() which is a separately-exec'd dsynth.
175 	 */
176 	if (UsingHooks)
177 		initbulk(childHookRun, MaxBulk);
178 
179 	/*
180 	 * Count up the packages, not counting dummies
181 	 */
182 	for (scan = pkgs; scan; scan = scan->bnext) {
183 		if ((scan->flags & PKGF_DUMMY) == 0)
184 			++BuildTotal;
185 	}
186 
187 	doHook(NULL, "hook_run_start", HookRunStart, 1);
188 
189 	/*
190 	 * The pkg and pkg-static binaries are needed.  If already present
191 	 * then assume that the template is also valid, otherwise build
192 	 * both.
193 	 */
194 	scan = GetPkgPkg(pkgs);
195 
196 	/*
197 	 * Create our template.  The template will be missing pkg
198 	 * and pkg-static.
199 	 */
200 	if ((scan->flags & (PKGF_SUCCESS | PKGF_PACKAGED)) == 0) {
201 		/* force a fresh template */
202 		newtemplate = DoCreateTemplate(1);
203 	} else {
204 		newtemplate = DoCreateTemplate(0);
205 	}
206 
207 	/*
208 	 * This will clear the screen and set-up our gui, so sleep
209 	 * a little first in case the user wants to see what was
210 	 * printed before.
211 	 */
212 	sleep(2);
213 	pthread_mutex_lock(&WorkerMutex);
214 	startTime = time(NULL);
215 	RunStatsInit();
216 	RunStatsReset();
217 
218 	/*
219 	 * Build pkg/pkg-static.
220 	 */
221 	if ((scan->flags & (PKGF_SUCCESS | PKGF_PACKAGED)) == 0) {
222 		build_list = scan;
223 		build_tail = &scan->build_next;
224 		startbuild(&build_list, &build_tail);
225 		while (RunningWorkers == 1)
226 			waitbuild(1, 0);
227 
228 		if (scan->flags & PKGF_NOBUILD)
229 			dfatal("Unable to build 'pkg'");
230 		if (scan->flags & PKGF_ERROR)
231 			dfatal("Error building 'pkg'");
232 		if ((scan->flags & PKGF_SUCCESS) == 0)
233 			dfatal("Error building 'pkg'");
234 		newtemplate = 1;
235 	}
236 
237 	/*
238 	 * Install pkg/pkg-static into the template
239 	 */
240 	if (newtemplate) {
241 		char *buf;
242 		int rc;
243 
244 		asprintf(&buf,
245 			 "cd %s/Template; "
246 			 "tar --exclude '+*' --exclude '*/man/*' "
247 			 "-xvzpf %s/%s > /dev/null 2>&1",
248 			 BuildBase,
249 			 RepositoryPath,
250 			 scan->pkgfile);
251 		rc = system(buf);
252 		if (rc)
253 			dfatal("Command failed: %s\n", buf);
254 		freestrp(&buf);
255 	}
256 
257 	/*
258 	 * Calculate depi_depth, the longest chain of dependencies
259 	 * for who depends on me, weighted by powers of two.
260 	 */
261 	for (scan = pkgs; scan; scan = scan->bnext) {
262 		buildCalculateDepiDepth(scan);
263 	}
264 
265 	/*
266 	 * Nominal bulk build sequence
267 	 */
268 	while (haswork) {
269 		haswork = 0;
270 		fflush(stdout);
271 		for (scan = pkgs; scan; scan = scan->bnext) {
272 			ddprintf(0, "SCANLEAVES %08x %s\n",
273 				 scan->flags, scan->portdir);
274 			scan->flags |= PKGF_BUILDLOOP;
275 			/*
276 			 * NOTE: We must still find dependencies if PACKAGED
277 			 *	 to fill in the gaps, as some of them may
278 			 *	 need to be rebuilt.
279 			 */
280 			if (scan->flags & (PKGF_SUCCESS | PKGF_FAILURE |
281 					   PKGF_ERROR)) {
282 #if 0
283 				ddprintf(0, "%s: already built\n",
284 					 scan->portdir);
285 #endif
286 			} else {
287 				int ap = 0;
288 				build_find_leaves(NULL, scan, &build_tail,
289 						  &ap, &haswork, 0, first, 0);
290 				ddprintf(0, "TOPLEVEL %s %08x\n",
291 					 scan->portdir, ap);
292 			}
293 			scan->flags &= ~PKGF_BUILDLOOP;
294 			build_clear_trav(scan);
295 		}
296 		first = 0;
297 		fflush(stdout);
298 		startbuild(&build_list, &build_tail);
299 
300 		if (haswork == 0 && RunningWorkers) {
301 			waitbuild(RunningWorkers, 1);
302 			haswork = 1;
303 		}
304 	}
305 	pthread_mutex_unlock(&WorkerMutex);
306 
307 	RunStatsUpdateTop(0);
308 	RunStatsUpdateLogs();
309 	RunStatsSync();
310 	RunStatsDone();
311 
312 	doHook(NULL, "hook_run_end", HookRunEnd, 1);
313 	if (UsingHooks) {
314 		while ((bulk = getbulk()) != NULL)
315 			freebulk(bulk);
316 		donebulk();
317 	}
318 
319 	t = time(NULL) - startTime;
320 	h = t / 3600;
321 	m = t / 60 % 60;
322 	s = t % 60;
323 
324 	dlog(DLOG_ALL|DLOG_STDOUT,
325 		"\n"
326 		"Initial queue size: %d\n"
327 		"    packages built: %d\n"
328 		"           ignored: %d\n"
329 		"           skipped: %d\n"
330 		"            failed: %d\n"
331 		"\n"
332 		"Duration: %02d:%02d:%02d\n"
333 		"\n",
334 		BuildTotal,
335 		BuildSuccessCount,
336 		BuildIgnoreCount,
337 		BuildSkipCount,
338 		BuildFailCount,
339 		h, m, s);
340 }
341 
342 /*
343  * Traverse the packages (pkg) depends on recursively until we find
344  * a leaf to build or report as unbuildable.  Calculates and assigns a
345  * dependency count.  Returns all parallel-buildable packages.
346  *
347  * (pkg) itself is only added to the list if it is immediately buildable.
348  */
349 static
350 int
351 build_find_leaves(pkg_t *parent, pkg_t *pkg, pkg_t ***build_tailp,
352 		  int *app, int *hasworkp, int depth, int first,
353 		  int first_one_only)
354 {
355 	pkglink_t *link;
356 	pkg_t *scan;
357 	int idep_count = 0;
358 	int apsub;
359 	int dfirst_one_only;
360 	int ndepth;
361 	char *buf;
362 
363 	ndepth = depth + 1;
364 
365 	/*
366 	 * Already on build list, possibly in-progress, tell caller that
367 	 * it is not ready.
368 	 */
369 	ddprintf(ndepth, "sbuild_find_leaves %d %s %08x {\n",
370 		 depth, pkg->portdir, pkg->flags);
371 	if (pkg->flags & PKGF_BUILDLIST) {
372 		ddprintf(ndepth, "} (already on build list)\n");
373 		*app |= PKGF_NOTREADY;
374 		return (pkg->idep_count);
375 	}
376 
377 	/*
378 	 * Check dependencies
379 	 */
380 	PKGLIST_FOREACH(link, &pkg->idepon_list) {
381 		scan = link->pkg;
382 
383 		if (scan == NULL) {
384 			if (first_one_only)
385 				break;
386 			continue;
387 		}
388 		ddprintf(ndepth, "check %s %08x\t", scan->portdir, scan->flags);
389 
390 		/*
391 		 * If this dependency is to a DUMMY node it is a dependency
392 		 * only on the default flavor which is only the first node
393 		 * under this one, not all of them.
394 		 *
395 		 * DUMMY nodes can be marked SUCCESS so the build skips past
396 		 * them, but this doesn't mean that their sub-nodes succeeded.
397 		 * We have to check, so recurse even if it is marked
398 		 * successful.
399 		 *
400 		 * NOTE: The depth is not being for complex dependency type
401 		 *	 tests like it is in childInstallPkgDeps_recurse(),
402 		 *	 so we don't have to hicup it like we do in that
403 		 *	 procedure.
404 		 */
405 		dfirst_one_only = (scan->flags & PKGF_DUMMY) ? 1 : 0;
406 		if (dfirst_one_only)
407 			goto skip_to_flavor;
408 
409 		/*
410 		 * When accounting for a successful build, just bump
411 		 * idep_count by one.  scan->idep_count will heavily
412 		 * overlap packages that we count down multiple branches.
413 		 *
414 		 * We must still recurse through PACKAGED packages as
415 		 * some of their dependencies might be missing.
416 		 */
417 		if (scan->flags & PKGF_SUCCESS) {
418 			ddprintf(0, "SUCCESS - OK\n");
419 			++idep_count;
420 			if (first_one_only)
421 				break;
422 			continue;
423 		}
424 
425 		/*
426 		 * ERROR includes FAILURE, which is set in numerous situations
427 		 * including when NOBUILD state is processed.  So check for
428 		 * NOBUILD state first.
429 		 *
430 		 * An ERROR in a sub-package causes a NOBUILD in packages
431 		 * that depend on it.
432 		 */
433 		if (scan->flags & PKGF_NOBUILD) {
434 			ddprintf(0, "NOBUILD - OK "
435 				    "(propagate failure upward)\n");
436 			*app |= PKGF_NOBUILD_S;
437 			if (first_one_only)
438 				break;
439 			continue;
440 		}
441 		if (scan->flags & PKGF_ERROR) {
442 			ddprintf(0, "ERROR - OK (propagate failure upward)\n");
443 			*app |= PKGF_NOBUILD_S;
444 			if (first_one_only)
445 				break;
446 			continue;
447 		}
448 
449 		/*
450 		 * If already on build-list this dependency is not ready.
451 		 */
452 		if (scan->flags & PKGF_BUILDLIST) {
453 			ddprintf(0, " [BUILDLIST]");
454 			*app |= PKGF_NOTREADY;
455 		}
456 
457 		/*
458 		 * If not packaged this dependency is not ready for
459 		 * the caller.
460 		 */
461 		if ((scan->flags & PKGF_PACKAGED) == 0) {
462 			ddprintf(0, " [NOT_PACKAGED]");
463 			*app |= PKGF_NOTREADY;
464 		}
465 
466 		/*
467 		 * Reduce search complexity, if we have already processed
468 		 * scan in the traversal it will either already be on the
469 		 * build list or it will not be buildable.  Either way
470 		 * the parent is not buildable.
471 		 */
472 		if (scan->flags & PKGF_BUILDTRAV) {
473 			ddprintf(0, " [BUILDTRAV]\n");
474 			*app |= PKGF_NOTREADY;
475 			if (first_one_only)
476 				break;
477 			continue;
478 		}
479 skip_to_flavor:
480 
481 		/*
482 		 * Assert on dependency loop
483 		 */
484 		++idep_count;
485 		if (scan->flags & PKGF_BUILDLOOP) {
486 			dfatal("pkg dependency loop %s -> %s",
487 				parent->portdir, scan->portdir);
488 		}
489 
490 		/*
491 		 * NOTE: For debug tabbing purposes we use (ndepth + 1)
492 		 *	 here (i.e. depth + 2) in our iteration.
493 		 */
494 		scan->flags |= PKGF_BUILDLOOP;
495 		apsub = 0;
496 		ddprintf(0, " SUBRECURSION {\n");
497 		idep_count += build_find_leaves(pkg, scan, build_tailp,
498 						&apsub, hasworkp,
499 						ndepth + 1, first,
500 						dfirst_one_only);
501 		scan->flags &= ~PKGF_BUILDLOOP;
502 		*app |= apsub;
503 		if (apsub & PKGF_NOBUILD) {
504 			ddprintf(ndepth, "} (sub-nobuild)\n");
505 		} else if (apsub & PKGF_ERROR) {
506 			ddprintf(ndepth, "} (sub-error)\n");
507 		} else if (apsub & PKGF_NOTREADY) {
508 			ddprintf(ndepth, "} (sub-notready)\n");
509 		} else {
510 			ddprintf(ndepth, "} (sub-ok)\n");
511 		}
512 		if (first_one_only)
513 			break;
514 	}
515 	pkg->idep_count = idep_count;
516 	pkg->flags |= PKGF_BUILDTRAV;
517 
518 	/*
519 	 * Incorporate scan results into pkg state.
520 	 */
521 	if ((pkg->flags & PKGF_NOBUILD) == 0 && (*app & PKGF_NOBUILD)) {
522 		*hasworkp = 1;
523 	} else if ((pkg->flags & PKGF_ERROR) == 0 && (*app & PKGF_ERROR)) {
524 		*hasworkp = 1;
525 	}
526 	pkg->flags |= *app & ~PKGF_NOTREADY;
527 
528 	/*
529 	 * Clear PACKAGED bit if sub-dependencies aren't clean
530 	 */
531 	if ((pkg->flags & PKGF_PACKAGED) &&
532 	    (pkg->flags & (PKGF_NOTREADY|PKGF_ERROR|PKGF_NOBUILD))) {
533 		pkg->flags &= ~PKGF_PACKAGED;
534 		ddassert(pkg->pkgfile);
535 		asprintf(&buf, "%s/%s", RepositoryPath, pkg->pkgfile);
536 		if (remove(buf) < 0) {
537 			dlog(DLOG_ALL,
538 			     "[XXX] %s DELETE-PACKAGE %s (failed)\n",
539 			     pkg->portdir, buf);
540 		} else {
541 			dlog(DLOG_ALL,
542 			     "[XXX] %s DELETE-PACKAGE %s "
543 			     "(due to dependencies)\n",
544 			     pkg->portdir, buf);
545 		}
546 		freestrp(&buf);
547 		*hasworkp = 1;
548 	}
549 
550 	/*
551 	 * Set PKGF_NOBUILD_I if there is IGNORE data
552 	 */
553 	if (pkg->ignore)
554 		pkg->flags |= PKGF_NOBUILD_I;
555 
556 	/*
557 	 * Handle propagated flags
558 	 */
559 	if (pkg->flags & PKGF_ERROR) {
560 		/*
561 		 * This can only happen if the ERROR has already been
562 		 * processed and accounted for.
563 		 */
564 		ddprintf(depth, "} (ERROR - %s)\n", pkg->portdir);
565 	} else if (*app & PKGF_NOTREADY) {
566 		/*
567 		 * We don't set PKGF_NOTREADY in the pkg, it is strictly
568 		 * a transient flag propagated via build_find_leaves().
569 		 *
570 		 * Just don't add the package to the list.
571 		 *
572 		 * NOTE: Even if NOBUILD is set (meaning we could list it
573 		 *	 and let startbuild() finish it up as a skip, we
574 		 *	 don't process it to the list because we want to
575 		 *	 process all the dependencies, so someone doing a
576 		 *	 manual build can get more complete information and
577 		 *	 does not have to iterate each failed dependency one
578 		 *	 at a time.
579 		 */
580 		;
581 	} else if (pkg->flags & PKGF_SUCCESS) {
582 		ddprintf(depth, "} (SUCCESS - %s)\n", pkg->portdir);
583 	} else if (pkg->flags & PKGF_DUMMY) {
584 		/*
585 		 * Just mark dummy packages as successful when all of their
586 		 * sub-depends (flavors) complete successfully.  Note that
587 		 * dummy packages are not counted in the total, so do not
588 		 * decrement BuildTotal.
589 		 *
590 		 * Do not propagate *app up for the dummy node.  If there
591 		 * is a generic dependency (i.e. no flavor specified), the
592 		 * upper recursion detects PKGF_DUMMY and traverses through
593 		 * to the default flavor without checking error/nobuild
594 		 * flags.
595 		 */
596 		if (pkg->flags & PKGF_NOBUILD) {
597 			ddprintf(depth, "} (DUMMY/META - IGNORED)\n");
598 		} else {
599 			ddprintf(depth, "} (DUMMY/META - SUCCESS)\n");
600 			pkg->flags |= PKGF_SUCCESS;
601 			*hasworkp = 1;
602 			if (first) {
603 				dlog(DLOG_ALL | DLOG_FILTER,
604 				     "[XXX] %s META-ALREADY-BUILT\n",
605 				     pkg->portdir);
606 			} else {
607 				dlog(DLOG_SUCC, "[XXX] %s meta-node complete\n",
608 				     pkg->portdir);
609 				RunStatsUpdateCompletion(NULL, DLOG_SUCC, pkg,
610 							 "", "");
611 			}
612 		}
613 	} else if (pkg->flags & PKGF_PACKAGED) {
614 		/*
615 		 * We can just mark the pkg successful.  If this is
616 		 * the first pass, we count this as an initial pruning
617 		 * pass and reduce BuildTotal.
618 		 */
619 		ddprintf(depth, "} (PACKAGED - SUCCESS)\n");
620 		pkg->flags |= PKGF_SUCCESS;
621 		*hasworkp = 1;
622 		if (first) {
623 			dlog(DLOG_ALL | DLOG_FILTER,
624 			     "[XXX] %s ALREADY-BUILT\n",
625 			     pkg->portdir);
626 			--BuildTotal;
627 		}
628 	} else {
629 		/*
630 		 * All dependencies are successful, queue new work
631 		 * and indicate not-ready to the parent (since our
632 		 * package has to be built).
633 		 *
634 		 * NOTE: The NOBUILD case propagates to here as well
635 		 *	 and is ultimately handled by startbuild().
636 		 */
637 		*hasworkp = 1;
638 		if (pkg->flags & PKGF_NOBUILD_I)
639 			ddprintf(depth, "} (ADDLIST(IGNORE/BROKEN) - %s)\n",
640 				 pkg->portdir);
641 		else if (pkg->flags & PKGF_NOBUILD)
642 			ddprintf(depth, "} (ADDLIST(NOBUILD) - %s)\n",
643 				 pkg->portdir);
644 		else
645 			ddprintf(depth, "} (ADDLIST - %s)\n", pkg->portdir);
646 		pkg->flags |= PKGF_BUILDLIST;
647 		**build_tailp = pkg;
648 		*build_tailp = &pkg->build_next;
649 		*app |= PKGF_NOTREADY;
650 	}
651 
652 	return idep_count;
653 }
654 
655 static
656 void
657 build_clear_trav(pkg_t *pkg)
658 {
659 	pkglink_t *link;
660 	pkg_t *scan;
661 
662 	pkg->flags &= ~PKGF_BUILDTRAV;
663 	PKGLIST_FOREACH(link, &pkg->idepon_list) {
664 		scan = link->pkg;
665 		if (scan && (scan->flags & PKGF_BUILDTRAV))
666 			build_clear_trav(scan);
667 	}
668 }
669 
670 /*
671  * Calculate the longest chain of packages that depend on me.  The
672  * long the chain, the more important my package is to build earlier
673  * rather than later.
674  */
675 static int
676 buildCalculateDepiDepth(pkg_t *pkg)
677 {
678 	pkglink_t *link;
679 	pkg_t *scan;
680 	int best_depth = 0;
681 	int res;
682 
683 	if (pkg->depi_depth)
684 		return(pkg->depi_depth + 1);
685 	pkg->flags |= PKGF_BUILDLOOP;
686 	PKGLIST_FOREACH(link, &pkg->deponi_list) {
687 		scan = link->pkg;
688 		if (scan && (scan->flags & PKGF_BUILDLOOP) == 0) {
689 			res = buildCalculateDepiDepth(scan);
690 			if (best_depth < res)
691 				best_depth = res;
692 		}
693 	}
694 	pkg->flags &= ~PKGF_BUILDLOOP;
695 	pkg->depi_depth = best_depth;
696 
697 	return (best_depth + 1);
698 }
699 
700 /*
701  * Take a list of pkg ready to go, sort it, and assign it to worker
702  * slots.  This routine blocks in waitbuild() until it can dispose of
703  * the entire list.
704  *
705  * WorkerMutex is held by the caller.
706  */
707 static
708 void
709 startbuild(pkg_t **build_listp, pkg_t ***build_tailp)
710 {
711 	pkg_t *pkg;
712 	pkg_t **idep_ary;
713 	pkg_t **depi_ary;
714 	int count;
715 	int idep_index;
716 	int depi_index;
717 	int i;
718 	int n;
719 	worker_t *work;
720 	static int IterateWorker;
721 
722 	/*
723 	 * Nothing to do
724 	 */
725 	if (*build_listp == NULL)
726 		return;
727 
728 	/*
729 	 * Sort
730 	 */
731 	count = 0;
732 	for (pkg = *build_listp; pkg; pkg = pkg->build_next)
733 		++count;
734 	idep_ary = calloc(count, sizeof(pkg_t *));
735 	depi_ary = calloc(count, sizeof(pkg_t *));
736 
737 	count = 0;
738 	for (pkg = *build_listp; pkg; pkg = pkg->build_next) {
739 		idep_ary[count] = pkg;
740 		depi_ary[count] = pkg;
741 		++count;
742 	}
743 
744 	/*
745 	 * idep_ary - sorted by #of dependencies this pkg has.
746 	 * depi_ary - sorted by #of other packages that depend on this pkg.
747 	 */
748 	qsort(idep_ary, count, sizeof(pkg_t *), qsort_idep);
749 	qsort(depi_ary, count, sizeof(pkg_t *), qsort_depi);
750 
751 	idep_index = 0;
752 	depi_index = 0;
753 
754 	/*
755 	 * Half the workers build based on the highest depi count,
756 	 * the other half build based on the highest idep count.
757 	 *
758 	 * This is an attempt to get projects which many other projects
759 	 * depend on built first, but to also try to build large projects
760 	 * (which tend to have a lot of dependencies) earlier rather than
761 	 * later so the end of the bulk run doesn't inefficiently build
762 	 * the last few huge projects.
763 	 *
764 	 * Loop until we manage to assign slots to everyone.  We do not
765 	 * wait for build completion.
766 	 *
767 	 * This is the point where we handle DUMMY packages (these are
768 	 * dummy unflavored packages which 'cover' all the flavors for
769 	 * a package).  These are not real packages are marked SUCCESS
770 	 * at this time because their dependencies (the flavors) have all
771 	 * been built.
772 	 */
773 	while (idep_index != count || depi_index != count) {
774 		pkg_t *pkgi;
775 		pkg_t *ipkg;
776 
777 		/*
778 		 * Find candidate to start sorted by depi or idep.
779 		 */
780 		ipkg = NULL;
781 		while (idep_index < count) {
782 			ipkg = idep_ary[idep_index];
783 			if ((ipkg->flags &
784 			     (PKGF_SUCCESS | PKGF_FAILURE |
785 			      PKGF_ERROR | PKGF_RUNNING)) == 0) {
786 				break;
787 			}
788 			ipkg = NULL;
789 			++idep_index;
790 		}
791 
792 		pkgi = NULL;
793 		while (depi_index < count) {
794 			pkgi = depi_ary[depi_index];
795 			if ((pkgi->flags &
796 			     (PKGF_SUCCESS | PKGF_FAILURE |
797 			      PKGF_ERROR | PKGF_RUNNING)) == 0) {
798 				break;
799 			}
800 			pkgi = NULL;
801 			++depi_index;
802 		}
803 
804 		/*
805 		 * ipkg and pkgi must either both be NULL, or both
806 		 * be non-NULL.
807 		 */
808 		if (ipkg == NULL && pkgi == NULL)
809 			break;
810 		ddassert(ipkg && pkgi);
811 
812 		/*
813 		 * Handle the NOBUILD case right here, there's no point
814 		 * queueing it anywhere.
815 		 */
816 		if (ipkg->flags & PKGF_NOBUILD) {
817 			char *reason;
818 			char skipbuf[16];
819 			int scount;
820 
821 			scount = buildskipcount_dueto(ipkg, 1);
822 			buildskipcount_dueto(ipkg, 0);
823 			if (scount) {
824 				snprintf(skipbuf, sizeof(skipbuf), " %d",
825 					 scount);
826 			} else {
827 				skipbuf[0] = 0;
828 			}
829 
830 			ipkg->flags |= PKGF_FAILURE;
831 			ipkg->flags &= ~PKGF_BUILDLIST;
832 
833 			reason = buildskipreason(NULL, ipkg);
834 			if (ipkg->flags & PKGF_NOBUILD_I) {
835 				++BuildIgnoreCount;
836 				dlog(DLOG_IGN,
837 				     "[XXX] %s%s ignored due to %s\n",
838 				     ipkg->portdir, skipbuf, reason);
839 				RunStatsUpdateCompletion(NULL, DLOG_IGN, ipkg,
840 							 reason, skipbuf);
841 				doHook(ipkg, "hook_pkg_ignored",
842 				       HookPkgIgnored, 0);
843 			} else {
844 				++BuildSkipCount;
845 				dlog(DLOG_SKIP,
846 				     "[XXX] %s%s skipped due to %s\n",
847 				     ipkg->portdir, skipbuf, reason);
848 				RunStatsUpdateCompletion(NULL, DLOG_SKIP, ipkg,
849 							 reason, skipbuf);
850 				doHook(ipkg, "hook_pkg_skipped",
851 				       HookPkgSkipped, 0);
852 			}
853 			free(reason);
854 			++BuildCount;
855 			continue;
856 		}
857 		if (pkgi->flags & PKGF_NOBUILD) {
858 			char *reason;
859 			char skipbuf[16];
860 			int scount;
861 
862 			scount = buildskipcount_dueto(pkgi, 1);
863 			buildskipcount_dueto(pkgi, 0);
864 			if (scount) {
865 				snprintf(skipbuf, sizeof(skipbuf), " %d",
866 					 scount);
867 			} else {
868 				skipbuf[0] = 0;
869 			}
870 
871 			pkgi->flags |= PKGF_FAILURE;
872 			pkgi->flags &= ~PKGF_BUILDLIST;
873 
874 			reason = buildskipreason(NULL, pkgi);
875 			if (pkgi->flags & PKGF_NOBUILD_I) {
876 				++BuildIgnoreCount;
877 				dlog(DLOG_IGN, "[XXX] %s%s ignored due to %s\n",
878 				     pkgi->portdir, skipbuf, reason);
879 				RunStatsUpdateCompletion(NULL, DLOG_IGN, pkgi,
880 							 reason, skipbuf);
881 				doHook(pkgi, "hook_pkg_ignored",
882 				       HookPkgIgnored, 0);
883 			} else {
884 				++BuildSkipCount;
885 				dlog(DLOG_SKIP,
886 				     "[XXX] %s%s skipped due to %s\n",
887 				     pkgi->portdir, skipbuf, reason);
888 				RunStatsUpdateCompletion(NULL, DLOG_SKIP, pkgi,
889 							 reason, skipbuf);
890 				doHook(pkgi, "hook_pkg_skipped",
891 				       HookPkgSkipped, 0);
892 			}
893 			free(reason);
894 			++BuildCount;
895 			continue;
896 		}
897 
898 		/*
899 		 * Block while no slots are available.  waitbuild()
900 		 * will clean out any DONE states.
901 		 */
902 		while (RunningWorkers >= DynamicMaxWorkers ||
903 		       RunningWorkers >= MaxWorkers - FailedWorkers) {
904 			waitbuild(RunningWorkers, 1);
905 		}
906 
907 		/*
908 		 * Find an available worker slot, there should be at
909 		 * least one.
910 		 */
911 		for (i = 0; i < MaxWorkers; ++i) {
912 			n = IterateWorker % MaxWorkers;
913 			work = &WorkerAry[n];
914 
915 			if (work->state == WORKER_DONE ||
916 			    work->state == WORKER_FAILED) {
917 				workercomplete(work);
918 			}
919 			if (work->state == WORKER_NONE ||
920 			    work->state == WORKER_IDLE) {
921 				if (n <= MaxWorkers / 2) {
922 					startworker(pkgi, work);
923 				} else {
924 					startworker(ipkg, work);
925 				}
926 				/*RunStatsUpdate(work);*/
927 				break;
928 			}
929 			++IterateWorker;
930 		}
931 		ddassert(i != MaxWorkers);
932 	}
933 	RunStatsSync();
934 
935 	/*
936 	 * We disposed of the whole list
937 	 */
938 	free(idep_ary);
939 	free(depi_ary);
940 	*build_listp = NULL;
941 	*build_tailp = build_listp;
942 }
943 
944 typedef const pkg_t *pkg_tt;
945 
946 static int
947 qsort_idep(const void *pkg1_arg, const void *pkg2_arg)
948 {
949 	const pkg_t *pkg1 = *(const pkg_tt *)pkg1_arg;
950 	const pkg_t *pkg2 = *(const pkg_tt *)pkg2_arg;
951 
952 	return (pkg2->idep_count - pkg1->idep_count);
953 }
954 
955 static int
956 qsort_depi(const void *pkg1_arg, const void *pkg2_arg)
957 {
958 	const pkg_t *pkg1 = *(const pkg_tt *)pkg1_arg;
959 	const pkg_t *pkg2 = *(const pkg_tt *)pkg2_arg;
960 
961 	return ((pkg2->depi_count * pkg2->depi_depth) -
962 		(pkg1->depi_count * pkg1->depi_depth));
963 }
964 
965 /*
966  * Frontend starts a pkg up on a worker
967  *
968  * WorkerMutex must be held.
969  */
970 static void
971 startworker(pkg_t *pkg, worker_t *work)
972 {
973 	switch(work->state) {
974 	case WORKER_NONE:
975 		pthread_create(&work->td, NULL, childBuilderThread, work);
976 		work->state = WORKER_IDLE;
977 		/* fall through */
978 	case WORKER_IDLE:
979 		work->pkg_dep_size =
980 		childInstallPkgDeps_recurse(NULL, &pkg->idepon_list, 0, 1, 0);
981 		childInstallPkgDeps_recurse(NULL, &pkg->idepon_list, 1, 1, 0);
982 		RunningPkgDepSize += work->pkg_dep_size;
983 
984 		dlog(DLOG_ALL, "[%03d] START   %s "
985 			       "##idep=%02d depi=%02d/%02d dep=%-4.2fG\n",
986 		     work->index, pkg->portdir,
987 		     pkg->idep_count, pkg->depi_count, pkg->depi_depth,
988 		     (double)work->pkg_dep_size / (double)ONEGB);
989 
990 		cleanworker(work);
991 		pkg->flags |= PKGF_RUNNING;
992 		work->pkg = pkg;
993 		pthread_cond_signal(&work->cond);
994 		++RunningWorkers;
995 		/*RunStatsUpdate(work);*/
996 		break;
997 	case WORKER_PENDING:
998 	case WORKER_RUNNING:
999 	case WORKER_DONE:
1000 	case WORKER_FAILED:
1001 	case WORKER_FROZEN:
1002 	case WORKER_EXITING:
1003 	default:
1004 		dfatal("startworker: [%03d] Unexpected state %d for worker %d",
1005 		       work->index, work->state, work->index);
1006 		break;
1007 	}
1008 }
1009 
1010 static void
1011 cleanworker(worker_t *work)
1012 {
1013 	work->state = WORKER_PENDING;
1014 	work->flags = 0;
1015 	work->accum_error = 0;
1016 	work->start_time = time(NULL);
1017 }
1018 
1019 /*
1020  * Frontend finishes up a completed pkg on a worker.
1021  *
1022  * If the worker is in a FAILED state we clean the pkg out but (for now)
1023  * leave it in its failed state so we can debug.  At this point
1024  * workercomplete() will be called every once in a while on the state
1025  * and we have to deal with the NULL pkg.
1026  *
1027  * WorkerMutex must be held.
1028  */
1029 static void
1030 workercomplete(worker_t *work)
1031 {
1032 	pkg_t *pkg;
1033 	time_t t;
1034 	int h;
1035 	int m;
1036 	int s;
1037 
1038 	/*
1039 	 * Steady state FAILED case.
1040 	 */
1041 	if (work->state == WORKER_FAILED) {
1042 		if (work->pkg == NULL)
1043 			return;
1044 	}
1045 
1046 	t = time(NULL) - work->start_time;
1047 	h = t / 3600;
1048 	m = t / 60 % 60;
1049 	s = t % 60;
1050 
1051 	/*
1052 	 * Reduce total dep size
1053 	 */
1054 	RunningPkgDepSize -= work->pkg_dep_size;
1055 	RunningPkgDepSize -= work->memuse;
1056 	work->pkg_dep_size = 0;
1057 	work->memuse = 0;
1058 
1059 	/*
1060 	 * Process pkg out of the worker
1061 	 */
1062 	pkg = work->pkg;
1063 	if (pkg->flags & (PKGF_ERROR|PKGF_NOBUILD)) {
1064 		char skipbuf[16];
1065 		int scount;
1066 
1067 		pkg->flags |= PKGF_FAILURE;
1068 
1069 		scount = buildskipcount_dueto(pkg, 1);
1070 		buildskipcount_dueto(pkg, 0);
1071 		if (scount) {
1072 			snprintf(skipbuf, sizeof(skipbuf), " %d",
1073 				 scount);
1074 		} else {
1075 			skipbuf[0] = 0;
1076 		}
1077 
1078 		/*
1079 		 * This NOBUILD condition XXX can occur if the package is
1080 		 * not allowed to be built.
1081 		 */
1082 		if (pkg->flags & PKGF_NOBUILD) {
1083 			char *reason;
1084 
1085 			reason = buildskipreason(NULL, pkg);
1086 			if (pkg->flags & PKGF_NOBUILD_I) {
1087 				++BuildIgnoreCount;
1088 				dlog(DLOG_SKIP, "[%03d] IGNORD %s%s - %s\n",
1089 				     work->index, pkg->portdir,
1090 				     skipbuf, reason);
1091 				RunStatsUpdateCompletion(work, DLOG_SKIP, pkg,
1092 							 reason, skipbuf);
1093 				doHook(pkg, "hook_pkg_ignored",
1094 				       HookPkgIgnored, 0);
1095 			} else {
1096 				++BuildSkipCount;
1097 				dlog(DLOG_SKIP, "[%03d] SKIPPD %s%s - %s\n",
1098 				     work->index, pkg->portdir,
1099 				     skipbuf, reason);
1100 				RunStatsUpdateCompletion(work, DLOG_SKIP, pkg,
1101 							 reason, skipbuf);
1102 				doHook(pkg, "hook_pkg_skipped",
1103 				       HookPkgSkipped, 0);
1104 			}
1105 			free(reason);
1106 		} else {
1107 			++BuildFailCount;
1108 			dlog(DLOG_FAIL | DLOG_RED,
1109 			     "[%03d] FAILURE %s%s ##%16.16s %02d:%02d:%02d\n",
1110 			     work->index, pkg->portdir, skipbuf,
1111 			     getphasestr(work->phase),
1112 			     h, m, s);
1113 			RunStatsUpdateCompletion(work, DLOG_FAIL, pkg,
1114 						 skipbuf, "");
1115 			doHook(pkg, "hook_pkg_failure", HookPkgFailure, 0);
1116 		}
1117 	} else {
1118 		pkg->flags |= PKGF_SUCCESS;
1119 		++BuildSuccessCount;
1120 		dlog(DLOG_SUCC | DLOG_GRN,
1121 		     "[%03d] SUCCESS %s ##%02d:%02d:%02d\n",
1122 		     work->index, pkg->portdir, h, m, s);
1123 		RunStatsUpdateCompletion(work, DLOG_SUCC, pkg, "", "");
1124 		doHook(pkg, "hook_pkg_success", HookPkgSuccess, 0);
1125 	}
1126 	++BuildCount;
1127 	pkg->flags &= ~PKGF_BUILDLIST;
1128 	pkg->flags &= ~PKGF_RUNNING;
1129 	work->pkg = NULL;
1130 	--RunningWorkers;
1131 
1132 	if (work->state == WORKER_FAILED) {
1133 		dlog(DLOG_ALL, "[%03d] XXX/XXX WORKER IS IN A FAILED STATE\n",
1134 		     work->index);
1135 		++FailedWorkers;
1136 	} else if (work->flags & WORKERF_FREEZE) {
1137 		dlog(DLOG_ALL, "[%03d] FROZEN(DEBUG) %s\n",
1138 		     work->index, pkg->portdir);
1139 		work->state = WORKER_FROZEN;
1140 	} else {
1141 		work->state = WORKER_IDLE;
1142 	}
1143 }
1144 
1145 /*
1146  * Wait for one or more workers to complete.
1147  *
1148  * WorkerMutex must be held.
1149  */
1150 static void
1151 waitbuild(int whilematch, int dynamicmax)
1152 {
1153 	static time_t wblast_time;
1154 	static time_t dmlast_time;
1155 	struct timespec ts;
1156 	worker_t *work;
1157 	time_t t;
1158 	int i;
1159 
1160 	if (whilematch == 0)
1161 		whilematch = 1;
1162 
1163 	while (RunningWorkers == whilematch) {
1164 		for (i = 0; i < MaxWorkers; ++i) {
1165 			work = &WorkerAry[i];
1166 			if (work->state == WORKER_DONE ||
1167 			    work->state == WORKER_FAILED) {
1168 				workercomplete(work);
1169 			} else {
1170 				pthread_cond_signal(&work->cond);
1171 			}
1172 			RunStatsUpdate(work, NULL);
1173 		}
1174 		RunStatsUpdateTop(1);
1175 		RunStatsUpdateLogs();
1176 		RunStatsSync();
1177 		if (RunningWorkers == whilematch) {
1178 			clock_gettime(CLOCK_REALTIME, &ts);
1179 			ts.tv_sec += 1;
1180 			ts.tv_nsec = 0;
1181 			pthread_cond_timedwait(&WorkerCond, &WorkerMutex, &ts);
1182 		}
1183 
1184 		/*
1185 		 * Dynamically reduce MaxWorkers based on the load.  When
1186 		 * the load exceeds 2 x ncpus we reduce the number of workers
1187 		 * up to 75% of MaxWorkers @ (5 x ncpus) load.
1188 		 *
1189 		 * Dynamically reduce MaxWorkers based on swap use, starting
1190 		 * at 10% swap and up to 75% of MaxWorkers at 40% swap.
1191 		 *
1192 		 * NOTE! Generally speaking this allows more workers to be
1193 		 *	 configured which helps in two ways.  First it allows
1194 		 *	 a higher build rate for smaller packages.  Second
1195 		 *	 it allows dsynth to ratchet-down the number of slots
1196 		 *	 when large packages are forcing the load up.
1197 		 *
1198 		 *	 A high load doesn't hurt efficiency, but swap usage
1199 		 *	 due to loading the tmpfs in lots of worker slots up
1200 		 *	 with tons of pkg install's (pre-reqs for a build)
1201 		 *	 does.  Reducing the number of worker slots has a
1202 		 *	 huge beneficial effect on reducing swap use / paging.
1203 		 */
1204 		t = time(NULL);
1205 		if (dynamicmax && (wblast_time == 0 ||
1206 				   (unsigned)(t - wblast_time) >= 5)) {
1207 			double min_load = 1.5 * NumCores;
1208 			double max_load = 5.0 * NumCores;
1209 			double min_swap = 0.10;
1210 			double max_swap = 0.40;
1211 			double dload[3];
1212 			double dswap;
1213 			int max1;
1214 			int max2;
1215 			int max3;
1216 			int max_sel;
1217 			int noswap;
1218 
1219 			wblast_time = t;
1220 
1221 			/*
1222 			 * Cap based on load.  This is back-loaded.
1223 			 */
1224 			getloadavg(dload, 3);
1225 			adjloadavg(dload);
1226 			if (dload[0] < min_load) {
1227 				max1 = MaxWorkers;
1228 			} else if (dload[0] <= max_load) {
1229 				max1 = MaxWorkers -
1230 				       MaxWorkers * 0.75 *
1231 				       (dload[0] - min_load) /
1232 				       (max_load - min_load);
1233 			} else {
1234 				max1 = MaxWorkers * 25 / 100;
1235 			}
1236 
1237 			/*
1238 			 * Cap based on swap use.  This is back-loaded.
1239 			 */
1240 			dswap = getswappct(&noswap);
1241 			if (dswap < min_swap) {
1242 				max2 = MaxWorkers;
1243 			} else if (dswap <= max_swap) {
1244 				max2 = MaxWorkers -
1245 				       MaxWorkers * 0.75 *
1246 				       (dswap - min_swap) /
1247 				       (max_swap - min_swap);
1248 			} else {
1249 				max2 = MaxWorkers * 25 / 100;
1250 			}
1251 
1252 			/*
1253 			 * Cap based on aggregate pkg-dependency memory
1254 			 * use installed in worker slots.  This is
1255 			 * front-loaded.
1256 			 *
1257 			 * Since it can take a while for workers to retire
1258 			 * (to reduce RunningPkgDepSize), just set our
1259 			 * target 1 below the current run count to allow
1260 			 * jobs to retire without being replaced with new
1261 			 * jobs.
1262 			 *
1263 			 * In addition, in order to avoid a paging 'shock',
1264 			 * We enforce a 30 second-per-increment slow-start
1265 			 * once RunningPkgDepSize exceeds 1/2 the target.
1266 			 */
1267 			if (RunningPkgDepSize > PkgDepMemoryTarget) {
1268 				max3 = RunningWorkers - 1;
1269 			} else if (RunningPkgDepSize > PkgDepMemoryTarget / 2) {
1270 				if (dmlast_time == 0 ||
1271 				    (unsigned)(t - dmlast_time) >= 30) {
1272 					dmlast_time = t;
1273 					max3 = RunningWorkers + 1;
1274 				} else {
1275 					max3 = RunningWorkers;
1276 				}
1277 			} else {
1278 				max3 = MaxWorkers;
1279 			}
1280 
1281 			/*
1282 			 * Priority reduction, convert to DynamicMaxWorkers
1283 			 */
1284 			max_sel = max1;
1285 			if (max_sel > max2)
1286 				max_sel = max2;
1287 			if (max_sel > max3)
1288 				max_sel = max3;
1289 
1290 			/*
1291 			 * Restrict to allowed range, and also handle
1292 			 * slow-start.
1293 			 */
1294 			if (max_sel < 1)
1295 				max_sel = 1;
1296 			if (max_sel > DynamicMaxWorkers + 1)
1297 				max_sel = DynamicMaxWorkers + 1;
1298 			if (max_sel > MaxWorkers)
1299 				max_sel = MaxWorkers;
1300 
1301 			/*
1302 			 * Stop waiting if DynamicMaxWorkers is going to
1303 			 * increase.
1304 			 */
1305 			if (DynamicMaxWorkers < max1)
1306 				whilematch = -1;
1307 
1308 			/*
1309 			 * And adjust
1310 			 */
1311 			if (DynamicMaxWorkers != max1) {
1312 				dlog(DLOG_ALL | DLOG_FILTER,
1313 				     "[XXX] Load=%-6.2f(%2d) "
1314 				     "Swap=%-3.2f%%(%2d) "
1315 				     "Mem=%3.2fG(%2d) "
1316 				     "Adjust Workers %d->%d\n",
1317 				     dload[0], max1,
1318 				     dswap * 100.0, max2,
1319 				     RunningPkgDepSize / (double)ONEGB, max3,
1320 				     DynamicMaxWorkers, max_sel);
1321 				DynamicMaxWorkers = max_sel;
1322 			}
1323 		}
1324 	}
1325 }
1326 
1327 
1328 /*
1329  * Worker pthread (WorkerAry)
1330  *
1331  * This thread belongs to the dsynth master process and handled a worker slot.
1332  * (this_thread) -> WORKER fork/exec (WorkerPocess) -> (pty) -> sub-processes.
1333  */
1334 static void *
1335 childBuilderThread(void *arg)
1336 {
1337 	char *envary[1] = { NULL };
1338 	worker_t *work = arg;
1339 	wmsg_t wmsg;
1340 	pkg_t *pkg;
1341 	pid_t pid;
1342 	int status;
1343 	int flags;
1344 	volatile int dowait;
1345 	char slotbuf[8];
1346 	char fdbuf[8];
1347 	char flagsbuf[16];
1348 
1349 	pthread_mutex_lock(&WorkerMutex);
1350 	while (work->terminate == 0) {
1351 		dowait = 1;
1352 
1353 		switch(work->state) {
1354 		case WORKER_IDLE:
1355 			break;
1356 		case WORKER_PENDING:
1357 			/*
1358 			 * Fork the management process for the pkg operation
1359 			 * on this worker slot.
1360 			 *
1361 			 * This process will set up the environment, do the
1362 			 * mounts, will become the reaper, and will process
1363 			 * pipe commands and handle chroot operations.
1364 			 *
1365 			 * NOTE: If SOCK_CLOEXEC is not supported WorkerMutex
1366 			 *	 is sufficient to interlock F_SETFD FD_CLOEXEC
1367 			 *	 operations.
1368 			 */
1369 			ddassert(work->pkg);
1370 			if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC,
1371 				       PF_UNSPEC, work->fds)) {
1372 				dfatal_errno("socketpair() during worker fork");
1373 			}
1374 			snprintf(slotbuf, sizeof(slotbuf), "%d", work->index);
1375 			snprintf(fdbuf, sizeof(fdbuf), "3");
1376 
1377 			/*
1378 			 * Pass global flags and add-in the DEBUGSTOP if
1379 			 * the package is flagged for debugging.
1380 			 */
1381 			flags = WorkerProcFlags;
1382 			if (work->pkg->flags & PKGF_DEBUGSTOP) {
1383 				flags |= WORKER_PROC_DEBUGSTOP;
1384 			} else {
1385 				flags &= ~WORKER_PROC_DEBUGSTOP;
1386 			}
1387 			snprintf(flagsbuf, sizeof(flagsbuf), "%d", flags);
1388 
1389 			/*
1390 			 * fds[0] - master
1391 			 * fds[1] - slave
1392 			 *
1393 			 * We pass the salve descriptor in fd 3 and close all
1394 			 * other descriptors for security.
1395 			 */
1396 			pthread_mutex_unlock(&WorkerMutex);
1397 			pid = vfork();
1398 			if (pid == 0) {
1399 				close(work->fds[0]);
1400 				dup2(work->fds[1], 3);
1401 				closefrom(4);
1402 				fcntl(3, F_SETFD, 0);
1403 				execle(DSynthExecPath, DSynthExecPath,
1404 				       "-p", Profile,
1405 				       "WORKER", slotbuf, fdbuf,
1406 				       work->pkg->portdir, work->pkg->pkgfile,
1407 				       flagsbuf,
1408 				       NULL, envary);
1409 				write(2, "EXECLE FAILURE\n", 15);
1410 				_exit(1);
1411 			}
1412 			pthread_mutex_lock(&WorkerMutex);
1413 			close(work->fds[1]);
1414 			work->phase = PHASE_PENDING;
1415 			work->lines = 0;
1416 			work->memuse = 0;
1417 			work->pid = pid;
1418 			work->state = WORKER_RUNNING;
1419 			/* fall through */
1420 		case WORKER_RUNNING:
1421 			/*
1422 			 * Poll for status updates, if NULL is returned
1423 			 * and status is non-zero, the communications link
1424 			 * failed unexpectedly.
1425 			 */
1426 			pkg = work->pkg;
1427 			pthread_mutex_unlock(&WorkerMutex);
1428 			status = ipcreadmsg(work->fds[0], &wmsg);
1429 			pthread_mutex_lock(&WorkerMutex);
1430 
1431 			if (status == 0) {
1432 				/*
1433 				 * Normal message, can include normal
1434 				 * termination which changes us over
1435 				 * to another state.
1436 				 */
1437 				dowait = 0;
1438 				switch(wmsg.cmd) {
1439 				case WMSG_CMD_INSTALL_PKGS:
1440 					wmsg.cmd = WMSG_RES_INSTALL_PKGS;
1441 					wmsg.status = childInstallPkgDeps(work);
1442 					pthread_mutex_unlock(&WorkerMutex);
1443 					ipcwritemsg(work->fds[0], &wmsg);
1444 					pthread_mutex_lock(&WorkerMutex);
1445 					break;
1446 				case WMSG_CMD_STATUS_UPDATE:
1447 					work->phase = wmsg.phase;
1448 					work->lines = wmsg.lines;
1449 					if (work->memuse != wmsg.memuse) {
1450 						RunningPkgDepSize +=
1451 						wmsg.memuse - work->memuse;
1452 						work->memuse = wmsg.memuse;
1453 					}
1454 					break;
1455 				case WMSG_CMD_SUCCESS:
1456 					work->flags |= WORKERF_SUCCESS;
1457 					break;
1458 				case WMSG_CMD_FAILURE:
1459 					work->flags |= WORKERF_FAILURE;
1460 					break;
1461 				case WMSG_CMD_FREEZEWORKER:
1462 					work->flags |= WORKERF_FREEZE;
1463 					break;
1464 				default:
1465 					break;
1466 				}
1467 				RunStatsUpdate(work, NULL);
1468 				RunStatsSync();
1469 			} else {
1470 				close(work->fds[0]);
1471 				pthread_mutex_unlock(&WorkerMutex);
1472 				while (waitpid(work->pid, &status, 0) < 0 &&
1473 				       errno == EINTR) {
1474 					;
1475 				}
1476 				pthread_mutex_lock(&WorkerMutex);
1477 
1478 				if (work->flags & WORKERF_SUCCESS) {
1479 					pkg->flags |= PKGF_SUCCESS;
1480 					work->state = WORKER_DONE;
1481 				} else if (work->flags & WORKERF_FAILURE) {
1482 					pkg->flags |= PKGF_FAILURE;
1483 					work->state = WORKER_DONE;
1484 				} else {
1485 					pkg->flags |= PKGF_FAILURE;
1486 					work->state = WORKER_FAILED;
1487 				}
1488 				work->flags |= WORKERF_STATUS_UPDATE;
1489 				pthread_cond_signal(&WorkerCond);
1490 			}
1491 			break;
1492 		case WORKER_DONE:
1493 			/*
1494 			 * pkg remains attached until frontend processes the
1495 			 * completion.  The frontend will then set the state
1496 			 * back to idle.
1497 			 */
1498 			break;
1499 		case WORKER_FAILED:
1500 			/*
1501 			 * A worker failure means that the worker did not
1502 			 * send us a WMSG_CMD_SUCCESS or WMSG_CMD_FAILURE
1503 			 * ipc before terminating.
1504 			 *
1505 			 * We just sit in this state until the front-end
1506 			 * does something about it.
1507 			 */
1508 			break;
1509 		case WORKER_FROZEN:
1510 			/*
1511 			 * A worker getting frozen is debug-related.  We
1512 			 * just sit in this state (likely forever).
1513 			 */
1514 			break;
1515 		default:
1516 			dfatal("worker: [%03d] Unexpected state %d "
1517 			       "for worker %d",
1518 			       work->index, work->state, work->index);
1519 			/* NOT REACHED */
1520 			break;
1521 		}
1522 
1523 		/*
1524 		 * The dsynth frontend will poll us approximately once
1525 		 * a second (its variable).
1526 		 */
1527 		if (dowait)
1528 			pthread_cond_wait(&work->cond, &WorkerMutex);
1529 	}
1530 
1531 	/*
1532 	 * Scrap the comm socket if running, this should cause the worker
1533 	 * process to kill its sub-programs and cleanup.
1534 	 */
1535 	if (work->state == WORKER_RUNNING) {
1536 		pthread_mutex_unlock(&WorkerMutex);
1537 		close(work->fds[0]);
1538 		while (waitpid(work->pid, &status, 0) < 0 &&
1539 		       errno == EINTR);
1540 		pthread_mutex_lock(&WorkerMutex);
1541 	}
1542 
1543 	/*
1544 	 * Final handshake
1545 	 */
1546 	work->state = WORKER_EXITING;
1547 	pthread_cond_signal(&WorkerCond);
1548 	pthread_mutex_unlock(&WorkerMutex);
1549 
1550 	return NULL;
1551 }
1552 
1553 /*
1554  * Install all the binary packages (we have already built them) that
1555  * the current work package depends on, without duplicates, in a script
1556  * which will be run from within the specified work jail.
1557  *
1558  * Locked by WorkerMutex (global)
1559  */
1560 static int
1561 childInstallPkgDeps(worker_t *work)
1562 {
1563 	char *buf;
1564 	FILE *fp;
1565 
1566 	if (PKGLIST_EMPTY(&work->pkg->idepon_list))
1567 		return 0;
1568 
1569 	asprintf(&buf, "%s/tmp/dsynth_install_pkgs", work->basedir);
1570 	fp = fopen(buf, "w");
1571 	ddassert(fp != NULL);
1572 	fprintf(fp, "#!/bin/sh\n");
1573 	fprintf(fp, "#\n");
1574 	fchmod(fileno(fp), 0755);
1575 
1576 	childInstallPkgDeps_recurse(fp, &work->pkg->idepon_list, 0, 1, 0);
1577 	childInstallPkgDeps_recurse(fp, &work->pkg->idepon_list, 1, 1, 0);
1578 	fprintf(fp, "\nexit 0\n");
1579 	fclose(fp);
1580 	freestrp(&buf);
1581 
1582 	return 1;
1583 }
1584 
1585 /*
1586  * Recursive child install dependencies.
1587  *
1588  * first_one_only is only specified if the pkg the list comes from
1589  * is a generic unflavored package that has flavors, telling us to
1590  * dive the first flavor only.
1591  *
1592  * However, in nearly all cases this flag will now be zero because
1593  * this code now dives the first flavor when encountering a dummy node
1594  * and clears nfirst on success.  Hence if you are asking why 'nfirst'
1595  * is set to 1, and then zero, instead of just being removed entirely,
1596  * it is because there might still be an edge case here.
1597  */
1598 static size_t
1599 childInstallPkgDeps_recurse(FILE *fp, pkglink_t *list, int undoit,
1600 			    int depth, int first_one_only)
1601 {
1602 	pkglink_t *link;
1603 	pkg_t *pkg;
1604 	size_t tot = 0;
1605 	int ndepth;
1606 	int nfirst;
1607 
1608 	PKGLIST_FOREACH(link, list) {
1609 		pkg = link->pkg;
1610 
1611 		/*
1612 		 * We don't want to mess up our depth test just below if
1613 		 * a DUMMY node had to be inserted.  The nodes under the
1614 		 * dummy node.
1615 		 *
1616 		 * The elements under a dummy node represent all the flabor,
1617 		 * a dependency that directly references a dummy node only
1618 		 * uses the first flavor (first_one_only / nfirst).
1619 		 */
1620 		ndepth = (pkg->flags & PKGF_DUMMY) ? depth : depth + 1;
1621 		nfirst = (pkg->flags & PKGF_DUMMY) ? 1 : 0;
1622 
1623 		/*
1624 		 * We only need all packages for the top-level dependencies.
1625 		 * The deeper ones only need DEP_TYPE_LIB and DEP_TYPE_RUN
1626 		 * (types greater than DEP_TYPE_BUILD) since they are already
1627 		 * built.
1628 		 */
1629 		if (depth > 1 && link->dep_type <= DEP_TYPE_BUILD) {
1630 			if (first_one_only)
1631 				break;
1632 			continue;
1633 		}
1634 
1635 		/*
1636 		 * If this is a dummy node with no package, the originator
1637 		 * is requesting a flavored package.  We select the default
1638 		 * flavor which we presume is the first one.
1639 		 */
1640 		if (pkg->pkgfile == NULL && (pkg->flags & PKGF_DUMMY)) {
1641 			pkg_t *spkg = pkg->idepon_list.next->pkg;
1642 
1643 			if (spkg) {
1644 				if (fp) {
1645 					fprintf(fp,
1646 						"echo 'UNFLAVORED %s -> use "
1647 						"%s'\n",
1648 						pkg->portdir,
1649 						spkg->portdir);
1650 				}
1651 				pkg = spkg;
1652 				nfirst = 0;
1653 			} else {
1654 				if (fp) {
1655 					fprintf(fp,
1656 						"echo 'CANNOT FIND DEFAULT "
1657 						"FLAVOR FOR %s'\n",
1658 						pkg->portdir);
1659 				}
1660 			}
1661 		}
1662 
1663 		if (undoit) {
1664 			if (pkg->dsynth_install_flg == 1) {
1665 				pkg->dsynth_install_flg = 0;
1666 				tot += childInstallPkgDeps_recurse(fp,
1667 							    &pkg->idepon_list,
1668 							    undoit,
1669 							    ndepth, nfirst);
1670 			}
1671 			if (first_one_only)
1672 				break;
1673 			continue;
1674 		}
1675 
1676 		if (pkg->dsynth_install_flg) {
1677 			if (DebugOpt >= 2 && pkg->pkgfile && fp) {
1678 				fprintf(fp, "echo 'AlreadyHave %s'\n",
1679 					pkg->pkgfile);
1680 			}
1681 			if (first_one_only)
1682 				break;
1683 			continue;
1684 		}
1685 
1686 		tot += childInstallPkgDeps_recurse(fp, &pkg->idepon_list,
1687 						   undoit, ndepth, nfirst);
1688 		if (pkg->dsynth_install_flg) {
1689 			if (first_one_only)
1690 				break;
1691 			continue;
1692 		}
1693 		pkg->dsynth_install_flg = 1;
1694 
1695 		/*
1696 		 * Generate package installation command
1697 		 */
1698 		if (fp && pkg->pkgfile) {
1699 			fprintf(fp, "echo 'Installing /packages/All/%s'\n",
1700 				pkg->pkgfile);
1701 			fprintf(fp, "pkg install -q -U -y /packages/All/%s "
1702 				"|| exit 1\n",
1703 				pkg->pkgfile);
1704 		} else if (fp) {
1705 			fprintf(fp, "echo 'CANNOT FIND PKG FOR %s'\n",
1706 				pkg->portdir);
1707 		}
1708 
1709 		if (pkg->pkgfile) {
1710 			struct stat st;
1711 			char *path;
1712 			char *ptr;
1713 
1714 			asprintf(&path, "%s/%s", RepositoryPath, pkg->pkgfile);
1715 			ptr = strrchr(pkg->pkgfile, '.');
1716 			if (stat(path, &st) == 0) {
1717 				if (strcmp(ptr, ".tar") == 0)
1718 					tot += st.st_size;
1719 				else if (strcmp(ptr, ".tgz") == 0)
1720 					tot += st.st_size * 3;
1721 				else if (strcmp(ptr, ".txz") == 0)
1722 					tot += st.st_size * 5;
1723 				else if (strcmp(ptr, ".tbz") == 0)
1724 					tot += st.st_size * 3;
1725 				else
1726 					tot += st.st_size * 2;
1727 			}
1728 			free(path);
1729 		}
1730 		if (first_one_only)
1731 			break;
1732 	}
1733 	return tot;
1734 }
1735 
1736 /*
1737  * Worker process interactions.
1738  *
1739  * The worker process is responsible for managing the build of a single
1740  * package.  It is exec'd by the master dsynth and only loads the
1741  * configuration.
1742  *
1743  * This process does not run in the chroot.  It will become the reaper for
1744  * all sub-processes and it will enter the chroot to execute various phases.
1745  * It catches SIGINTR, SIGHUP, and SIGPIPE and will iterate, terminate, and
1746  * reap all sub-process upon kill or exit.
1747  *
1748  * The command line forwarded to this function is:
1749  *
1750  *	WORKER slot# socketfd portdir/subdir
1751  *
1752  * TERM=dumb
1753  * USER=root
1754  * HOME=/root
1755  * LANG=C
1756  * SSL_NO_VERIFY_PEER=1
1757  * USE_PACKAGE_DEPENDS_ONLY=1
1758  * PORTSDIR=/xports
1759  * PORT_DBDIR=/options		For ports options
1760  * PACKAGE_BUILDING=yes		Don't build packages that aren't legally
1761  *				buildable for a binary repo.
1762  * PKG_DBDIR=/var/db/pkg
1763  * PKG_CACHEDIR=/var/cache/pkg
1764  * PKG_CREATE_VERBOSE=yes	Ensure periodic output during packaging
1765  * (custom environment)
1766  * PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
1767  * UNAME_s=DragonFly		(example)
1768  * UNAME_v=DragonFly 5.7-SYNTH	(example)
1769  * UNAME_p=x86_64		(example)
1770  * UNAME_m=x86_64		(example)
1771  * UNAME_r=5.7-SYNTH		(example)
1772  * NO_DEPENDS=yes		(conditional based on phase)
1773  * DISTDIR=/distfiles
1774  * WRKDIRPREFIX=/construction
1775  * BATCH=yes
1776  * MAKE_JOBS_NUMBER=n
1777  *
1778  * SETUP:
1779  *	ldconfig -R
1780  *	/usr/local/sbin/pkg-static install /packages/All/<the pkg pkg>
1781  *	/usr/local/sbin/pkg-static install /packages/All/<pkg>
1782  *			(for all dependencies)
1783  *
1784  * PHASES: 		make -C path FLAVOR=flavor <phase>
1785  *	check-sanity
1786  *	pkg-depends
1787  *	fetch-depends
1788  *	fetch
1789  *	checksum
1790  *	extract-depends
1791  *	extract
1792  *	patch-depends
1793  *	patch
1794  *	build-depends
1795  *	lib-depends
1796  *	configure
1797  *	build
1798  *	run-depends
1799  *	stage
1800  *	test		(skipped)
1801  *	check-plist	('dsynth test blahblah' or 'dsynth -D everything' only)
1802  *	package		 e.g. /construction/lang/perl5.28/pkg/perl5-5.28.2.txz
1803  *	install-mtree	(skipped)
1804  *	install		(skipped)
1805  *	deinstall	(skipped)
1806  */
1807 void
1808 WorkerProcess(int ac, char **av)
1809 {
1810 	wmsg_t wmsg;
1811 	int fd;
1812 	int slot;
1813 	int tmpfd;
1814 	int pkgpkg = 0;
1815 	int status;
1816 	int len;
1817 	int do_install_phase;
1818 	char *portdir;
1819 	char *pkgfile;
1820 	char *flavor;
1821 	char *buf;
1822 	worker_t *work;
1823 	bulk_t *bulk;
1824 	pkg_t pkg;
1825 	buildenv_t *benv;
1826 	FILE *fp;
1827 
1828 	/*
1829 	 * Parse arguments
1830 	 */
1831 	if (ac != 6) {
1832 		dlog(DLOG_ALL, "WORKER PROCESS %d- bad arguments\n", getpid());
1833 		exit(1);
1834 	}
1835 	slot = strtol(av[1], NULL, 0);
1836 	fd = strtol(av[2], NULL, 0);	/* master<->slave messaging */
1837 	portdir = av[3];
1838 	pkgfile = av[4];
1839 	flavor = strchr(portdir, '@');
1840 	if (flavor) {
1841 		*flavor++ = 0;
1842 		asprintf(&buf, "@%s", flavor);
1843 		WorkerFlavorPrt = buf;
1844 		buf = NULL;	/* safety */
1845 	}
1846 	WorkerProcFlags = strtol(av[5], NULL, 0);
1847 
1848 	bzero(&wmsg, sizeof(wmsg));
1849 
1850 	setproctitle("[%02d] WORKER STARTUP  %s%s",
1851 		     slot, portdir, WorkerFlavorPrt);
1852 
1853 	if (strcmp(portdir, "ports-mgmt/pkg") == 0)
1854 		pkgpkg = 1;
1855 
1856 	signal(SIGTERM, phaseTerminateSignal);
1857 	signal(SIGINT, phaseTerminateSignal);
1858 	signal(SIGHUP, phaseTerminateSignal);
1859 
1860 	/*
1861 	 * Set up the environment
1862 	 */
1863 	setenv("TERM", "dumb", 1);
1864 	setenv("USER", "root", 1);
1865 	setenv("HOME", "/root", 1);
1866 	setenv("LANG", "C", 1);
1867 	setenv("SSL_NO_VERIFY_PEER", "1", 1);
1868 
1869 	addbuildenv("USE_PACKAGE_DEPENDS_ONLY", "yes", BENV_MAKECONF);
1870 	addbuildenv("PORTSDIR", "/xports", BENV_MAKECONF);
1871 	addbuildenv("PORT_DBDIR", "/options", BENV_MAKECONF);
1872 	addbuildenv("PKG_DBDIR", "/var/db/pkg", BENV_MAKECONF);
1873 	addbuildenv("PKG_CACHEDIR", "/var/cache/pkg", BENV_MAKECONF);
1874 	addbuildenv("PKG_SUFX", UsePkgSufx, BENV_MAKECONF);
1875 	if (WorkerProcFlags & WORKER_PROC_DEVELOPER)
1876 		addbuildenv("DEVELOPER", "1", BENV_MAKECONF);
1877 
1878 	/*
1879 	 * CCache is a horrible unreliable hack but... leave the
1880 	 * mechanism in-place in case someone has a death wish.
1881 	 */
1882 	if (UseCCache) {
1883 		addbuildenv("WITH_CCACHE_BUILD", "yes", BENV_MAKECONF);
1884 		addbuildenv("CCACHE_DIR", "/ccache", BENV_MAKECONF);
1885 	}
1886 
1887 	addbuildenv("UID", "0", BENV_MAKECONF);
1888 	addbuildenv("ARCH", ArchitectureName, BENV_MAKECONF);
1889 
1890 #ifdef __DragonFly__
1891 	addbuildenv("OPSYS", "DragonFly", BENV_MAKECONF);
1892 	addbuildenv("DFLYVERSION", VersionFromParamHeader, BENV_MAKECONF);
1893 	addbuildenv("OSVERSION", "9999999", BENV_MAKECONF);
1894 #else
1895 #error "Need OS-specific data to generate make.conf"
1896 #endif
1897 
1898 	addbuildenv("OSREL", ReleaseName, BENV_MAKECONF);
1899 	addbuildenv("_OSRELEASE", VersionOnlyName, BENV_MAKECONF);
1900 
1901 	setenv("PATH",
1902 	       "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin",
1903 	       1);
1904 
1905 	setenv("UNAME_s", OperatingSystemName, 1);
1906 	setenv("UNAME_v", VersionName, 1);
1907 	setenv("UNAME_p", ArchitectureName, 1);
1908 	setenv("UNAME_m", MachineName, 1);
1909 	setenv("UNAME_r", ReleaseName, 1);
1910 
1911 	addbuildenv("DISTDIR", "/distfiles", BENV_MAKECONF);
1912 	addbuildenv("WRKDIRPREFIX", "/construction", BENV_MAKECONF);
1913 	addbuildenv("BATCH", "yes", BENV_MAKECONF);
1914 
1915 	/*
1916 	 * Special consideration
1917 	 *
1918 	 * PACKAGE_BUILDING	- Disallow packaging ports which do not allow
1919 	 *			  for binary distribution.
1920 	 *
1921 	 * PKG_CREATE_VERBOSE	- Ensure periodic output during the packaging
1922 	 *			  process to avoid a watchdog timeout.
1923 	 *
1924 	 */
1925 	addbuildenv("PACKAGE_BUILDING", "yes", BENV_MAKECONF);
1926 	addbuildenv("PKG_CREATE_VERBOSE", "yes", BENV_MAKECONF);
1927 	asprintf(&buf, "%d", MaxJobs);
1928 	addbuildenv("MAKE_JOBS_NUMBER", buf, BENV_MAKECONF);
1929 	freestrp(&buf);
1930 
1931 	if (flavor)
1932 		setenv("FLAVOR", flavor, 1);
1933 
1934 	/*
1935 	 * Become the reaper
1936 	 */
1937 	if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) < 0)
1938 		dfatal_errno("procctl() - Cannot become reaper");
1939 
1940 	/*
1941 	 * Initialize a worker structure
1942 	 */
1943 	DoInitBuild(slot);
1944 
1945 	bzero(&pkg, sizeof(pkg));
1946 	pkg.portdir = portdir;		/* sans flavor */
1947 	pkg.pkgfile = pkgfile;
1948 	if (strchr(portdir, '/'))
1949 		len = strchr(portdir, '/') - portdir;
1950 	else
1951 		len = 0;
1952 
1953 	/*
1954 	 * Setup the logfile
1955 	 */
1956 	asprintf(&pkg.logfile,
1957 		 "%s/%*.*s___%s%s%s.log",
1958 		 LogsPath, len, len, portdir,
1959 		 ((portdir[len] == '/') ? portdir + len + 1 : portdir + len),
1960 		 (flavor ? "@" : ""),
1961 		 (flavor ? flavor : ""));
1962 	tmpfd = open(pkg.logfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
1963 	if (tmpfd >= 0) {
1964 		if (DebugOpt >= 2) {
1965 			dlog(DLOG_ALL, "[%03d] %s LOGFILE %s\n",
1966 			     slot, pkg.portdir, pkg.logfile);
1967 		}
1968 		close(tmpfd);
1969 	} else {
1970 		dlog(DLOG_ALL, "[%03d] LOGFILE %s (create failed)\n",
1971 		     slot, pkg.logfile);
1972 	}
1973 
1974 	/*
1975 	 * Setup the work structure.  Because this is an exec'd sub-process,
1976 	 * there is only one work structure.
1977 	 */
1978 	work = &WorkerAry[0];
1979 	work->flavor = flavor;
1980 	work->fds[0] = fd;
1981 	work->pkg = &pkg;
1982 	work->start_time = time(NULL);
1983 
1984 	/*
1985 	 * Do mounts
1986 	 */
1987 	SigWork = work;
1988 	setproctitle("[%02d] WORKER MOUNTS   %s%s",
1989 		     slot, portdir, WorkerFlavorPrt);
1990 	DoWorkerMounts(work);
1991 
1992 	/*
1993 	 * Generate an /etc/make.conf in the build base
1994 	 */
1995 	asprintf(&buf, "%s/etc/make.conf", work->basedir);
1996 	fp = fopen(buf, "w");
1997 	dassert_errno(fp, "Unable to create %s\n", buf);
1998 	for (benv = BuildEnv; benv; benv = benv->next) {
1999 		if (benv->type & BENV_PKGLIST)
2000 			continue;
2001 		if ((benv->type & BENV_CMDMASK) == BENV_MAKECONF) {
2002 			if (DebugOpt >= 2) {
2003 				dlog(DLOG_ALL, "[%03d] ENV %s=%s\n",
2004 				     slot, benv->label, benv->data);
2005 			}
2006 			fprintf(fp, "%s=%s\n", benv->label, benv->data);
2007 		}
2008 	}
2009 	fclose(fp);
2010 	freestrp(&buf);
2011 
2012 	/*
2013 	 * Set up our hooks
2014 	 */
2015 	if (UsingHooks)
2016 		initbulk(childHookRun, MaxBulk);
2017 
2018 	/*
2019 	 * Start phases
2020 	 */
2021 	wmsg.cmd = WMSG_CMD_INSTALL_PKGS;
2022 	ipcwritemsg(fd, &wmsg);
2023 	status = ipcreadmsg(fd, &wmsg);
2024 	if (status < 0 || wmsg.cmd != WMSG_RES_INSTALL_PKGS)
2025 		dfatal("pkg installation handshake failed");
2026 	do_install_phase = wmsg.status;
2027 
2028 	wmsg.cmd = WMSG_CMD_STATUS_UPDATE;
2029 	wmsg.phase = PHASE_INSTALL_PKGS;
2030 	wmsg.lines = 0;
2031 
2032 	status = ipcwritemsg(fd, &wmsg);
2033 
2034 	if (pkgpkg) {
2035 		dophase(work, &wmsg,
2036 			WDOG5, PHASE_PACKAGE, "package");
2037 	} else {
2038 		if (do_install_phase) {
2039 			dophase(work, &wmsg,
2040 				WDOG4, PHASE_INSTALL_PKGS, "setup");
2041 		}
2042 		dophase(work, &wmsg,
2043 			WDOG2, PHASE_CHECK_SANITY, "check-sanity");
2044 		dophase(work, &wmsg,
2045 			WDOG2, PHASE_PKG_DEPENDS, "pkg-depends");
2046 		dophase(work, &wmsg,
2047 			WDOG7, PHASE_FETCH_DEPENDS, "fetch-depends");
2048 		dophase(work, &wmsg,
2049 			WDOG7, PHASE_FETCH, "fetch");
2050 		dophase(work, &wmsg,
2051 			WDOG2, PHASE_CHECKSUM, "checksum");
2052 		dophase(work, &wmsg,
2053 			WDOG3, PHASE_EXTRACT_DEPENDS, "extract-depends");
2054 		dophase(work, &wmsg,
2055 			WDOG3, PHASE_EXTRACT, "extract");
2056 		dophase(work, &wmsg,
2057 			WDOG2, PHASE_PATCH_DEPENDS, "patch-depends");
2058 		dophase(work, &wmsg,
2059 			WDOG2, PHASE_PATCH, "patch");
2060 		dophase(work, &wmsg,
2061 			WDOG5, PHASE_BUILD_DEPENDS, "build-depends");
2062 		dophase(work, &wmsg,
2063 			WDOG5, PHASE_LIB_DEPENDS, "lib-depends");
2064 		dophase(work, &wmsg,
2065 			WDOG3, PHASE_CONFIGURE, "configure");
2066 		dophase(work, &wmsg,
2067 			WDOG9, PHASE_BUILD, "build");
2068 		dophase(work, &wmsg,
2069 			WDOG5, PHASE_RUN_DEPENDS, "run-depends");
2070 		dophase(work, &wmsg,
2071 			WDOG5, PHASE_STAGE, "stage");
2072 #if 0
2073 		dophase(work, &wmsg,
2074 			WDOG5, PHASE_TEST, "test");
2075 #endif
2076 		if (WorkerProcFlags & WORKER_PROC_CHECK_PLIST) {
2077 			dophase(work, &wmsg,
2078 				WDOG1, PHASE_CHECK_PLIST, "check-plist");
2079 		}
2080 		dophase(work, &wmsg,
2081 			WDOG5, PHASE_PACKAGE, "package");
2082 #if 0
2083 		dophase(work, &wmsg,
2084 			WDOG5, PHASE_INSTALL_MTREE, "install-mtree");
2085 		dophase(work, &wmsg,
2086 			WDOG5, PHASE_INSTALL, "install");
2087 		dophase(work, &wmsg,
2088 			WDOG5, PHASE_DEINSTALL, "deinstall");
2089 #endif
2090 	}
2091 
2092 	if (MasterPtyFd >= 0) {
2093 		close(MasterPtyFd);
2094 		MasterPtyFd = -1;
2095 	}
2096 
2097 	setproctitle("[%02d] WORKER CLEANUP  %s%s",
2098 		     slot, portdir, WorkerFlavorPrt);
2099 
2100 	/*
2101 	 * Copy the package to the repo.
2102 	 */
2103 	if (work->accum_error == 0) {
2104 		char *b1;
2105 		char *b2;
2106 
2107 		asprintf(&b1, "%s/construction/%s/pkg/%s",
2108 			 work->basedir, pkg.portdir, pkg.pkgfile);
2109 		asprintf(&b2, "%s/%s", RepositoryPath, pkg.pkgfile);
2110 		if (copyfile(b1, b2)) {
2111 			++work->accum_error;
2112 			dlog(DLOG_ALL, "[%03d] %s Unable to copy %s to %s\n",
2113 			     work->index, pkg.portdir, b1, b2);
2114 		}
2115 		free(b1);
2116 		free(b2);
2117 	}
2118 
2119 	/*
2120 	 * Unmount, unless we are in DebugStopMode.
2121 	 */
2122 	if ((WorkerProcFlags & WORKER_PROC_DEBUGSTOP) == 0)
2123 		DoWorkerUnmounts(work);
2124 
2125 	/*
2126 	 * Send completion status to master dsynth worker thread.
2127 	 */
2128 	if (work->accum_error) {
2129 		wmsg.cmd = WMSG_CMD_FAILURE;
2130 	} else {
2131 		wmsg.cmd = WMSG_CMD_SUCCESS;
2132 	}
2133 	ipcwritemsg(fd, &wmsg);
2134 	if (WorkerProcFlags & WORKER_PROC_DEBUGSTOP) {
2135 		wmsg.cmd = WMSG_CMD_FREEZEWORKER;
2136 		ipcwritemsg(fd, &wmsg);
2137 	}
2138 	if (UsingHooks) {
2139 		while ((bulk = getbulk()) != NULL)
2140 			freebulk(bulk);
2141 		donebulk();
2142 	}
2143 }
2144 
2145 static void
2146 dophase(worker_t *work, wmsg_t *wmsg, int wdog, int phaseid, const char *phase)
2147 {
2148 	pkg_t *pkg = work->pkg;
2149 	char buf[1024];
2150 	pid_t pid;
2151 	int status;
2152 	int ms;
2153 	pid_t wpid;
2154 	int wpid_reaped;
2155 	int fdlog;
2156 	time_t start_time;
2157 	time_t last_time;
2158 	time_t next_time;
2159 	time_t wdog_time;
2160 	FILE *fp;
2161 
2162 	if (work->accum_error)
2163 		return;
2164 	setproctitle("[%02d] WORKER %-8.8s %s%s",
2165 		     work->index, phase, pkg->portdir, WorkerFlavorPrt);
2166 	wmsg->phase = phaseid;
2167 	if (ipcwritemsg(work->fds[0], wmsg) < 0) {
2168 		dlog(DLOG_ALL, "[%03d] %s Lost Communication with dsynth, "
2169 		     "aborting worker\n",
2170 		     work->index, pkg->portdir);
2171 		++work->accum_error;
2172 		return;
2173 	}
2174 
2175 	/*
2176 	 * Execute the port make command in chroot on a pty.
2177 	 */
2178 	fflush(stdout);
2179 	fflush(stderr);
2180 	if (MasterPtyFd >= 0) {
2181 		int slavefd;
2182 
2183 		/*
2184 		 * NOTE: We can't open the slave in the child because the
2185 		 *	 master may race a disconnection test.  If we open
2186 		 *	 it in the parent our close() will flush any pending
2187 		 *	 output not read by the master (which is the same
2188 		 *	 parent process) and deadlock.
2189 		 *
2190 		 *	 Solve this by hand-shaking the slave tty to give
2191 		 *	 the master time to close its slavefd (after this
2192 		 *	 section).
2193 		 *
2194 		 *	 Leave the tty defaults intact, which also likely
2195 		 *	 means it will be in line-buffered mode, so handshake
2196 		 *	 with a full line.
2197 		 *
2198 		 * TODO: Our handshake probably echos back to the master pty
2199 		 *	 due to tty echo, and ends up in the log, so just
2200 		 *	 pass through a newline.
2201 		 */
2202 		slavefd = open(ptsname(MasterPtyFd), O_RDWR);
2203 		dassert_errno(slavefd >= 0, "Cannot open slave pty");
2204 
2205 		/*
2206 		 * Now do the fork.
2207 		 */
2208 		pid = fork();
2209 		if (pid == 0) {
2210 			login_tty(slavefd);
2211 			/* login_tty() closes slavefd */
2212 		} else {
2213 			close(slavefd);
2214 		}
2215 	} else {
2216 		/*
2217 		 * Initial MasterPtyFd for the slot, just use forkpty().
2218 		 */
2219 		pid = forkpty(&MasterPtyFd, NULL, NULL, NULL);
2220 	}
2221 
2222 	/*
2223 	 * The slave must make sure the master has time to close slavefd
2224 	 * in the re-use case before going its merry way.  The master needs
2225 	 * to set terminal modes and the window as well.
2226 	 */
2227 	if (pid == 0) {
2228 		/*
2229 		 * Slave nices itself and waits for handshake
2230 		 */
2231 		char ttybuf[2];
2232 
2233 		/*
2234 		 * Self-nice to be nice (ignore any error)
2235 		 */
2236 		if (NiceOpt)
2237 			setpriority(PRIO_PROCESS, 0, NiceOpt);
2238 
2239 		read(0, ttybuf, 1);
2240 	} else {
2241 		/*
2242 		 * We are going through a pty, so set the tty modes to
2243 		 * Set tty modes so we do not get ^M's in the log files.
2244 		 *
2245 		 * This isn't fatal if it doesn't work.  Remember that
2246 		 * our output goes through the pty to the management
2247 		 * process which will log it.
2248 		 */
2249 		struct termios tio;
2250 		struct winsize win;
2251 
2252 		if (tcgetattr(MasterPtyFd, &tio) == 0) {
2253 			tio.c_oflag |= OPOST | ONOCR;
2254 			tio.c_oflag &= ~(OCRNL | ONLCR);
2255 			tio.c_iflag |= ICRNL;
2256 			tio.c_iflag &= ~(INLCR | IGNCR);
2257 			if (tcsetattr(MasterPtyFd, TCSANOW, &tio)) {
2258 				printf("tcsetattr failed: %s\n",
2259 				       strerror(errno));
2260 			}
2261 
2262 			/*
2263 			 * Give the tty a non-zero columns field.
2264 			 * This fixes at least one port (textproc/po4a)
2265 			 */
2266 			if (ioctl(MasterPtyFd, TIOCGWINSZ, &win) == 0) {
2267 				win.ws_col = 80;
2268 				ioctl(MasterPtyFd, TIOCSWINSZ, &win);
2269 			} else {
2270 				printf("TIOCGWINSZ failed: %s\n",
2271 				       strerror(errno));
2272 			}
2273 
2274 		} else {
2275 			printf("tcgetattr failed: %s\n", strerror(errno));
2276 		}
2277 
2278 		/*
2279 		 * Master issues handshake
2280 		 */
2281 		write(MasterPtyFd, "\n", 1);
2282 	}
2283 
2284 	if (pid == 0) {
2285 		/*
2286 		 * Additional phase-specific environment variables
2287 		 *
2288 		 * - Do not try to process missing depends outside of the
2289 		 *   depends phases.  Also relies on USE_PACKAGE_DEPENDS_ONLY
2290 		 *   in the make.conf.
2291 		 */
2292 		switch(phaseid) {
2293 		case PHASE_CHECK_SANITY:
2294 		case PHASE_FETCH:
2295 		case PHASE_CHECKSUM:
2296 		case PHASE_EXTRACT:
2297 		case PHASE_PATCH:
2298 		case PHASE_CONFIGURE:
2299 		case PHASE_STAGE:
2300 		case PHASE_TEST:
2301 		case PHASE_CHECK_PLIST:
2302 		case PHASE_INSTALL_MTREE:
2303 		case PHASE_INSTALL:
2304 		case PHASE_DEINSTALL:
2305 			break;
2306 		case PHASE_PKG_DEPENDS:
2307 		case PHASE_FETCH_DEPENDS:
2308 		case PHASE_EXTRACT_DEPENDS:
2309 		case PHASE_PATCH_DEPENDS:
2310 		case PHASE_BUILD_DEPENDS:
2311 		case PHASE_LIB_DEPENDS:
2312 		case PHASE_RUN_DEPENDS:
2313 			break;
2314 		default:
2315 			setenv("NO_DEPENDS", "1", 1);
2316 			break;
2317 		}
2318 
2319 		/*
2320 		 * Clean-up, chdir, and chroot.
2321 		 */
2322 		closefrom(3);
2323 		if (chdir(work->basedir) < 0)
2324 			dfatal_errno("chdir in phase initialization");
2325 		if (chroot(work->basedir) < 0)
2326 			dfatal_errno("chroot in phase initialization");
2327 
2328 		/*
2329 		 * We have a choice here on how to handle stdin (fd 0).
2330 		 * We can leave it connected to the pty in which case
2331 		 * the build will just block if it tries to ask a
2332 		 * question (and the watchdog will kill it, eventually),
2333 		 * or we can try to EOF the pty, or we can attach /dev/null
2334 		 * to descriptor 0.
2335 		 */
2336 		if (NullStdinOpt) {
2337 			int fd;
2338 
2339 			fd = open("/dev/null", O_RDWR);
2340 			dassert_errno(fd >= 0, "cannot open /dev/null");
2341 			if (fd != 0) {
2342 				dup2(fd, 0);
2343 				close(fd);
2344 			}
2345 		}
2346 
2347 		/*
2348 		 * Execute the appropriate command.
2349 		 */
2350 		switch(phaseid) {
2351 		case PHASE_INSTALL_PKGS:
2352 			snprintf(buf, sizeof(buf), "/tmp/dsynth_install_pkgs");
2353 			execl(buf, buf, NULL);
2354 			break;
2355 		default:
2356 			snprintf(buf, sizeof(buf), "/xports/%s", pkg->portdir);
2357 			execl(MAKE_BINARY, MAKE_BINARY, "-C", buf, phase, NULL);
2358 			break;
2359 		}
2360 		_exit(1);
2361 	}
2362 	fcntl(MasterPtyFd, F_SETFL, O_NONBLOCK);
2363 
2364 	if (pid < 0) {
2365 		dlog(DLOG_ALL, "[%03d] %s Fork Failed: %s\n",
2366 		     work->index, pkg->logfile, strerror(errno));
2367 		++work->accum_error;
2368 		return;
2369 	}
2370 
2371 	SigPid = pid;
2372 
2373 	fdlog = open(pkg->logfile, O_RDWR|O_CREAT|O_APPEND, 0644);
2374 	if (fdlog < 0) {
2375 		dlog(DLOG_ALL, "[%03d] %s Cannot open logfile '%s': %s\n",
2376 		     work->index, pkg->portdir,
2377 		     pkg->logfile, strerror(errno));
2378 	}
2379 
2380 	snprintf(buf, sizeof(buf),
2381 		 "----------------------------------------"
2382 		 "---------------------------------------\n"
2383 		 "-- Phase: %s\n"
2384 		 "----------------------------------------"
2385 		 "---------------------------------------\n",
2386 		 phase);
2387 	write(fdlog, buf, strlen(buf));
2388 
2389 	start_time = time(NULL);
2390 	last_time = start_time;
2391 	wdog_time = start_time;
2392 	wpid_reaped = 0;
2393 
2394 	status = 0;
2395 	for (;;) {
2396 		ms = mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time);
2397 		if (ms == MPTY_FAILED) {
2398 			dlog(DLOG_ALL,
2399 			     "[%03d] %s lost pty in phase %s, terminating\n",
2400 			     work->index, pkg->portdir, phase);
2401 			break;
2402 		}
2403 		if (ms == MPTY_EOF)
2404 			break;
2405 
2406 		/*
2407 		 * Generally speaking update status once a second.
2408 		 * This also allows us to detect if the management
2409 		 * dsynth process has gone away.
2410 		 */
2411 		next_time = time(NULL);
2412 		if (next_time != last_time) {
2413 			double dload[3];
2414 			double dv;
2415 			int wdog_scaled;
2416 
2417 			/*
2418 			 * Send status update to the worker management thread
2419 			 * in the master dsynth process.  Remember, *WE* are
2420 			 * the worker management process sub-fork.
2421 			 */
2422 			if (ipcwritemsg(work->fds[0], wmsg) < 0)
2423 				break;
2424 			last_time = next_time;
2425 
2426 			/*
2427 			 * Watchdog scaling
2428 			 */
2429 			getloadavg(dload, 3);
2430 			adjloadavg(dload);
2431 			dv = dload[2] / NumCores;
2432 			if (dv < (double)NumCores) {
2433 				wdog_scaled = wdog;
2434 			} else {
2435 				if (dv > 4.0 * NumCores)
2436 					dv = 4.0 * NumCores;
2437 				wdog_scaled = wdog * dv / NumCores;
2438 			}
2439 
2440 			/*
2441 			 * Watchdog
2442 			 */
2443 			if (next_time - wdog_time >= wdog_scaled * 60) {
2444 				snprintf(buf, sizeof(buf),
2445 					 "\n--------\n"
2446 					 "WATCHDOG TIMEOUT FOR %s in %s "
2447 					 "after %d minutes\n"
2448 					 "Killing pid %d\n"
2449 					 "--------\n",
2450 					 pkg->portdir, phase, wdog_scaled, pid);
2451 				if (fdlog >= 0)
2452 					write(fdlog, buf, strlen(buf));
2453 				dlog(DLOG_ALL,
2454 				     "[%03d] %s WATCHDOG TIMEOUT in %s "
2455 				     "after %d minutes (%d min scaled)\n",
2456 				     work->index, pkg->portdir, phase,
2457 				     wdog, wdog_scaled);
2458 				kill(pid, SIGKILL);
2459 				++work->accum_error;
2460 				break;
2461 			}
2462 		}
2463 
2464 		/*
2465 		 * Check process exit.  Normally the pty will EOF
2466 		 * but if background processes remain we need to
2467 		 * check here to see if our primary exec is done,
2468 		 * so we can break out and reap those processes.
2469 		 *
2470 		 * Generally reap any other processes we have inherited
2471 		 * while we are here.
2472 		 */
2473 		do {
2474 			wpid = wait3(&status, WNOHANG, NULL);
2475 		} while (wpid > 0 && wpid != pid);
2476 		if (wpid == pid && WIFEXITED(status)) {
2477 			wpid_reaped = 1;
2478 			break;
2479 		}
2480 	}
2481 
2482 	next_time = time(NULL);
2483 
2484 	setproctitle("[%02d] WORKER EXITREAP %s%s",
2485 		     work->index, pkg->portdir, WorkerFlavorPrt);
2486 
2487 	/*
2488 	 * We usually get here due to a mpty EOF, but not always as there
2489 	 * could be persistent processes still holding the slave.  Finish
2490 	 * up getting the exit status for the main process we are waiting
2491 	 * on and clean out any data left on the MasterPtyFd (as it could
2492 	 * be blocking the exit).
2493 	 */
2494 	while (wpid_reaped == 0) {
2495 		(void)mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time);
2496 		wpid = waitpid(pid, &status, WNOHANG);
2497 		if (wpid == pid && WIFEXITED(status)) {
2498 			wpid_reaped = 1;
2499 			break;
2500 		}
2501 		if (wpid < 0 && errno != EINTR) {
2502 			break;
2503 		}
2504 
2505 		/*
2506 		 * Safety.  The normal phase waits until the fork/exec'd
2507 		 * pid finishes, causing a pty EOF on exit (the slave
2508 		 * descriptor is closed by the kernel on exit so the
2509 		 * process should already have exited).
2510 		 *
2511 		 * However, it is also possible to get here if the pty fails
2512 		 * for some reason.  In this case, make sure that the process
2513 		 * is killed.
2514 		 */
2515 		kill(pid, SIGKILL);
2516 	}
2517 
2518 	/*
2519 	 * Clean out anything left on the pty but don't wait around
2520 	 * because there could be background processes preventing the
2521 	 * slave side from closing.
2522 	 */
2523 	while (mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time) == MPTY_DATA)
2524 		;
2525 
2526 	/*
2527 	 * Report on the exit condition.  If the pid was somehow lost
2528 	 * (probably due to someone gdb'ing the process), assume an error.
2529 	 */
2530 	if (wpid_reaped) {
2531 		if (WEXITSTATUS(status)) {
2532 			dlog(DLOG_ALL | DLOG_FILTER,
2533 			     "[%03d] %s Build phase '%s' failed exit %d\n",
2534 			     work->index, pkg->portdir, phase,
2535 			     WEXITSTATUS(status));
2536 			++work->accum_error;
2537 		}
2538 	} else {
2539 		dlog(DLOG_ALL, "[%03d] %s Build phase '%s' failed - lost pid\n",
2540 		     work->index, pkg->portdir, phase);
2541 		++work->accum_error;
2542 	}
2543 
2544 	/*
2545 	 * Kill any processes still running (sometimes processes end up in
2546 	 * the background during a dports build), and clean up any other
2547 	 * children that we have inherited.
2548 	 */
2549 	phaseReapAll();
2550 
2551 	/*
2552 	 * After the extraction phase add the space used by /construction
2553 	 * to the memory use.  This helps us reduce the amount of paging
2554 	 * we do due to extremely large package extractions (languages,
2555 	 * chromium, etc).
2556 	 *
2557 	 * (dsynth already estimated the space used by the package deps
2558 	 * up front, but this will help us further).
2559 	 */
2560 	if (work->accum_error == 0 && phaseid == PHASE_EXTRACT) {
2561 		struct statfs sfs;
2562 		char *b1;
2563 
2564 		asprintf(&b1, "%s/construction", work->basedir);
2565 		if (statfs(b1, &sfs) == 0) {
2566 			wmsg->memuse = (sfs.f_blocks - sfs.f_bfree) *
2567 				       sfs.f_bsize;
2568 			ipcwritemsg(work->fds[0], wmsg);
2569 		}
2570 	}
2571 
2572 	/*
2573 	 * Update log
2574 	 */
2575 	if (fdlog >= 0) {
2576 		struct stat st;
2577 		int h;
2578 		int m;
2579 		int s;
2580 
2581 		last_time = next_time - start_time;
2582 		s = last_time % 60;
2583 		m = last_time / 60 % 60;
2584 		h = last_time / 3600;
2585 
2586 		fp = fdopen(fdlog, "a");
2587 		if (fp == NULL) {
2588 			dlog(DLOG_ALL, "[%03d] %s Cannot fdopen fdlog: %s %d\n",
2589 			     work->index, pkg->portdir,
2590 			     strerror(errno), fstat(fdlog, &st));
2591 			close(fdlog);
2592 			goto skip;
2593 		}
2594 
2595 		fprintf(fp, "\n");
2596 		if (work->accum_error) {
2597 			fprintf(fp, "FAILED %02d:%02d:%02d\n", h, m, s);
2598 		} else {
2599 			if (phaseid == PHASE_EXTRACT && wmsg->memuse) {
2600 				fprintf(fp, "Extracted Memory Use: %6.2fM\n",
2601 					wmsg->memuse / (1024.0 * 1024.0));
2602 			}
2603 			fprintf(fp, "SUCCEEDED %02d:%02d:%02d\n", h, m, s);
2604 		}
2605 		last_time = next_time - work->start_time;
2606 		s = last_time % 60;
2607 		m = last_time / 60 % 60;
2608 		h = last_time / 3600;
2609 		if (phaseid == PHASE_PACKAGE) {
2610 			fprintf(fp, "TOTAL TIME %02d:%02d:%02d\n", h, m, s);
2611 		}
2612 		fprintf(fp, "\n");
2613 		fclose(fp);
2614 skip:
2615 		;
2616 	}
2617 
2618 }
2619 
2620 static void
2621 phaseReapAll(void)
2622 {
2623 	struct reaper_status rs;
2624 	int status;
2625 
2626 	while (procctl(P_PID, getpid(), PROC_REAP_STATUS, &rs) == 0) {
2627 		if ((rs.flags & PROC_REAP_ACQUIRE) == 0)
2628 			break;
2629 		if (rs.pid_head < 0)
2630 			break;
2631 		if (kill(rs.pid_head, SIGKILL) == 0) {
2632 			while (waitpid(rs.pid_head, &status, 0) < 0)
2633 				;
2634 		}
2635 	}
2636 	while (wait3(&status, 0, NULL) > 0)
2637 		;
2638 }
2639 
2640 static void
2641 phaseTerminateSignal(int sig __unused)
2642 {
2643 	if (CopyFileFd >= 0)
2644 		close(CopyFileFd);
2645 	if (MasterPtyFd >= 0)
2646 		close(MasterPtyFd);
2647 	if (SigPid > 1)
2648 		kill(SigPid, SIGKILL);
2649 	phaseReapAll();
2650 	if (SigWork)
2651 		DoWorkerUnmounts(SigWork);
2652 	exit(1);
2653 }
2654 
2655 static
2656 char *
2657 buildskipreason(pkglink_t *parent, pkg_t *pkg)
2658 {
2659 	pkglink_t *link;
2660 	pkg_t *scan;
2661 	char *reason = NULL;
2662 	char *ptr;
2663 	size_t tot;
2664 	size_t len;
2665 	pkglink_t stack;
2666 
2667 	if ((pkg->flags & PKGF_NOBUILD_I) && pkg->ignore)
2668 		asprintf(&reason, "%s ", pkg->ignore);
2669 
2670 	tot = 0;
2671 	PKGLIST_FOREACH(link, &pkg->idepon_list) {
2672 #if 0
2673 		if (link->dep_type > DEP_TYPE_BUILD)
2674 			continue;
2675 #endif
2676 		scan = link->pkg;
2677 		if (scan == NULL)
2678 			continue;
2679 		if ((scan->flags & (PKGF_ERROR | PKGF_NOBUILD)) == 0)
2680 			continue;
2681 		if (scan->flags & PKGF_NOBUILD) {
2682 			stack.pkg = scan;
2683 			stack.next = parent;
2684 			ptr = buildskipreason(&stack, scan);
2685 			len = strlen(scan->portdir) + strlen(ptr) + 8;
2686 			reason = realloc(reason, tot + len);
2687 			snprintf(reason + tot, len, "%s->%s",
2688 				 scan->portdir, ptr);
2689 			free(ptr);
2690 		} else {
2691 			len = strlen(scan->portdir) + 8;
2692 			reason = realloc(reason, tot + len);
2693 			snprintf(reason + tot, len, "%s", scan->portdir);
2694 		}
2695 
2696 		/*
2697 		 * Don't try to print the entire graph
2698 		 */
2699 		if (parent)
2700 			break;
2701 		tot += strlen(reason + tot);
2702 		reason[tot++] = ' ';
2703 		reason[tot] = 0;
2704 	}
2705 	return (reason);
2706 }
2707 
2708 /*
2709  * Count number of packages that would be skipped due to the
2710  * specified package having failed.
2711  *
2712  * Call with mode 1 to count, and mode 0 to clear the
2713  * cumulative rscan flag (used to de-duplicate the count).
2714  *
2715  * Must be serialized.
2716  */
2717 static int
2718 buildskipcount_dueto(pkg_t *pkg, int mode)
2719 {
2720 	pkglink_t *link;
2721 	pkg_t *scan;
2722 	int total;
2723 
2724 	total = 0;
2725 	PKGLIST_FOREACH(link, &pkg->deponi_list) {
2726 		scan = link->pkg;
2727 		if (scan == NULL || scan->rscan == mode)
2728 			continue;
2729 		scan->rscan = mode;
2730 		++total;
2731 		total += buildskipcount_dueto(scan, mode);
2732 	}
2733 	return total;
2734 }
2735 
2736 /*
2737  * The master ptyfd is in non-blocking mode.  Drain up to 1024 bytes
2738  * and update wmsg->lines and *wdog_timep as appropriate.
2739  *
2740  * This function will poll, stalling up to 1 second.
2741  */
2742 static int
2743 mptylogpoll(int ptyfd, int fdlog, wmsg_t *wmsg, time_t *wdog_timep)
2744 {
2745 	struct pollfd pfd;
2746 	char buf[1024];
2747 	ssize_t r;
2748 
2749 	pfd.fd = ptyfd;
2750 	pfd.events = POLLIN;
2751 	pfd.revents = 0;
2752 
2753 	poll(&pfd, 1, 1000);
2754 	if (pfd.revents) {
2755 		r = read(ptyfd, buf, sizeof(buf));
2756 		if (r > 0) {
2757 			*wdog_timep = time(NULL);
2758 			if (r > 0 && fdlog >= 0)
2759 				write(fdlog, buf, r);
2760 			while (--r >= 0) {
2761 				if (buf[r] == '\n')
2762 					++wmsg->lines;
2763 			}
2764 			return MPTY_DATA;
2765 		} else if (r < 0) {
2766 			if (errno != EINTR && errno != EAGAIN)
2767 				return MPTY_FAILED;
2768 			return MPTY_AGAIN;
2769 		} else if (r == 0) {
2770 			return MPTY_EOF;
2771 		}
2772 	}
2773 	return MPTY_AGAIN;
2774 }
2775 
2776 /*
2777  * Copy a (package) file from (src) to (dst), use an intermediate file and
2778  * rename to ensure that interruption does not leave us with a corrupt
2779  * package file.
2780  *
2781  * This is called by the WORKER process.
2782  *
2783  * (dsynth management thread -> WORKER process -> sub-processes)
2784  */
2785 #define COPYBLKSIZE	32768
2786 
2787 int
2788 copyfile(char *src, char *dst)
2789 {
2790 	char *tmp;
2791 	char *buf;
2792 	int fd1;
2793 	int fd2;
2794 	int error = 0;
2795 	int mask;
2796 	ssize_t r;
2797 
2798 	asprintf(&tmp, "%s.new", dst);
2799 	buf = malloc(COPYBLKSIZE);
2800 
2801 	mask = sigsetmask(sigmask(SIGTERM)|sigmask(SIGINT)|sigmask(SIGHUP));
2802 	fd1 = open(src, O_RDONLY|O_CLOEXEC);
2803 	fd2 = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
2804 	CopyFileFd = fd1;
2805 	sigsetmask(mask);
2806 	while ((r = read(fd1, buf, COPYBLKSIZE)) > 0) {
2807 		if (write(fd2, buf, r) != r)
2808 			error = 1;
2809 	}
2810 	if (r < 0)
2811 		error = 1;
2812 	mask = sigsetmask(sigmask(SIGTERM)|sigmask(SIGINT)|sigmask(SIGHUP));
2813 	CopyFileFd = -1;
2814 	close(fd1);
2815 	close(fd2);
2816 	sigsetmask(mask);
2817 	if (error) {
2818 		remove(tmp);
2819 	} else {
2820 		if (rename(tmp, dst)) {
2821 			error = 1;
2822 			remove(tmp);
2823 		}
2824 	}
2825 
2826 	freestrp(&buf);
2827 	freestrp(&tmp);
2828 
2829 	return error;
2830 }
2831 
2832 /*
2833  * doHook()
2834  *
2835  * primary process (threaded) - run_start, run_end, pkg_ignored, pkg_skipped
2836  * worker process  (threaded) - pkg_sucess, pkg_failure
2837  *
2838  * If waitfor is non-zero this hook will be serialized.
2839  */
2840 static void
2841 doHook(pkg_t *pkg, const char *id, const char *path, int waitfor)
2842 {
2843 	if (path == NULL)
2844 		return;
2845 	while (waitfor && getbulk() != NULL)
2846 		;
2847 	if (pkg)
2848 		queuebulk(pkg->portdir, id, path, pkg->pkgfile);
2849 	else
2850 		queuebulk(NULL, id, path, NULL);
2851 	while (waitfor && getbulk() != NULL)
2852 		;
2853 }
2854 
2855 /*
2856  * Execute hook (backend)
2857  *
2858  * s1 - portdir
2859  * s2 - id
2860  * s3 - script path
2861  * s4 - pkgfile		(if applicable)
2862  */
2863 static void
2864 childHookRun(bulk_t *bulk)
2865 {
2866 	const char *cav[MAXCAC];
2867 	buildenv_t benv[MAXCAC];
2868 	char buf1[128];
2869 	char buf2[128];
2870 	char buf3[128];
2871 	char buf4[128];
2872 	FILE *fp;
2873 	char *ptr;
2874 	size_t len;
2875 	pid_t pid;
2876 	int cac;
2877 	int bi;
2878 
2879 	cac = 0;
2880 	bi = 0;
2881 	bzero(benv, sizeof(benv));
2882 
2883 	cav[cac++] = bulk->s3;
2884 
2885 	benv[bi].label = "PROFILE";
2886 	benv[bi].data = Profile;
2887 	++bi;
2888 
2889 	benv[bi].label = "DIR_PACKAGES";
2890 	benv[bi].data = PackagesPath;
2891 	++bi;
2892 
2893 	benv[bi].label = "DIR_REPOSITORY";
2894 	benv[bi].data = RepositoryPath;
2895 	++bi;
2896 
2897 	benv[bi].label = "DIR_PORTS";
2898 	benv[bi].data = DPortsPath;
2899 	++bi;
2900 
2901 	benv[bi].label = "DIR_OPTIONS";
2902 	benv[bi].data = OptionsPath;
2903 	++bi;
2904 
2905 	benv[bi].label = "DIR_DISTFILES";
2906 	benv[bi].data = DistFilesPath;
2907 	++bi;
2908 
2909 	benv[bi].label = "DIR_LOGS";
2910 	benv[bi].data = LogsPath;
2911 	++bi;
2912 
2913 	benv[bi].label = "DIR_BUILDBASE";
2914 	benv[bi].data = BuildBase;
2915 	++bi;
2916 
2917 	if (strcmp(bulk->s2, "hook_run_start") == 0) {
2918 		snprintf(buf1, sizeof(buf1), "%d", BuildTotal);
2919 		benv[bi].label = "PORTS_QUEUED";
2920 		benv[bi].data = buf1;
2921 		++bi;
2922 	} else if (strcmp(bulk->s2, "hook_run_end") == 0) {
2923 		snprintf(buf1, sizeof(buf1), "%d", BuildSuccessCount);
2924 		benv[bi].label = "PORTS_BUILT";
2925 		benv[bi].data = buf1;
2926 		++bi;
2927 		snprintf(buf2, sizeof(buf2), "%d", BuildFailCount);
2928 		benv[bi].label = "PORTS_FAILED";
2929 		benv[bi].data = buf2;
2930 		++bi;
2931 		snprintf(buf3, sizeof(buf3), "%d", BuildIgnoreCount);
2932 		benv[bi].label = "PORTS_IGNORED";
2933 		benv[bi].data = buf3;
2934 		++bi;
2935 		snprintf(buf4, sizeof(buf4), "%d", BuildSkipCount);
2936 		benv[bi].label = "PORTS_SKIPPED";
2937 		benv[bi].data = buf4;
2938 		++bi;
2939 	} else {
2940 		/*
2941 		 * success, failure, ignored, skipped
2942 		 */
2943 		benv[bi].label = "RESULT";
2944 		if (strcmp(bulk->s2, "hook_pkg_success") == 0) {
2945 			benv[bi].data = "success";
2946 		} else if (strcmp(bulk->s2, "hook_pkg_failure") == 0) {
2947 			benv[bi].data = "failure";
2948 		} else if (strcmp(bulk->s2, "hook_pkg_ignored") == 0) {
2949 			benv[bi].data = "ignored";
2950 		} else if (strcmp(bulk->s2, "hook_pkg_skipped") == 0) {
2951 			benv[bi].data = "skipped";
2952 		} else {
2953 			dfatal("Unknown hook id: %s", bulk->s2);
2954 			/* NOT REACHED */
2955 		}
2956 		++bi;
2957 
2958 		/*
2959 		 * For compatibility with synth:
2960 		 *
2961 		 * ORIGIN does not include any @flavor, thus it is suitable
2962 		 * for finding the actual port directory/subdirectory.
2963 		 *
2964 		 * FLAVOR is set to ORIGIN if there is no flavor, otherwise
2965 		 * it is set to only the flavor sans the '@'.
2966 		 */
2967 		if ((ptr = strchr(bulk->s1, '@')) != NULL) {
2968 			snprintf(buf1, sizeof(buf1), "%*.*s",
2969 				 (int)(ptr - bulk->s1),
2970 				 (int)(ptr - bulk->s1),
2971 				 bulk->s1);
2972 			benv[bi].label = "ORIGIN";
2973 			benv[bi].data = buf1;
2974 			++bi;
2975 			benv[bi].label = "FLAVOR";
2976 			benv[bi].data = ptr + 1;
2977 			++bi;
2978 		} else {
2979 			benv[bi].label = "ORIGIN";
2980 			benv[bi].data = bulk->s1;
2981 			++bi;
2982 			benv[bi].label = "FLAVOR";
2983 			benv[bi].data = bulk->s1;
2984 			++bi;
2985 		}
2986 		benv[bi].label = "PKGNAME";
2987 		benv[bi].data = bulk->s4;
2988 		++bi;
2989 	}
2990 
2991 	benv[bi].label = NULL;
2992 	benv[bi].data = NULL;
2993 
2994 	fp = dexec_open(cav, cac, &pid, benv, 0, 0);
2995 	while ((ptr = fgetln(fp, &len)) != NULL)
2996 		;
2997 
2998 	if (dexec_close(fp, pid)) {
2999 		dlog(DLOG_ALL,
3000 		     "[XXX] %s SCRIPT %s (%s)\n",
3001 		     bulk->s1, bulk->s2, bulk->s3);
3002 	}
3003 }
3004 
3005 /*
3006  * Adjusts dload[0] by adding in t_pw (processes waiting on page-fault).
3007  * We don't want load reductions due to e.g. thrashing to cause dsynth
3008  * to increase the dynamic limit because it thinks the load is low.
3009  *
3010  * This has a desirable property.  If the system pager cannot keep up
3011  * with process demand t_pw will spike while loadavg will only drop
3012  * slowly, resulting in a high adjusted load calculation that causes
3013  * dsynth to quickly clamp-down the limit.  If the condition alleviates,
3014  * the limit will then rise slowly again, possibly even before existing
3015  * jobs are retired to meet the clamp-down from the original spike.
3016  */
3017 static void
3018 adjloadavg(double *dload)
3019 {
3020 #if defined(__DragonFly__)
3021 	struct vmtotal total;
3022 	size_t size;
3023 
3024 	size = sizeof(total);
3025 	if (sysctlbyname("vm.vmtotal", &total, &size, NULL, 0) == 0) {
3026 		dload[0] += (double)total.t_pw;
3027 	}
3028 #else
3029 	dload[0] += 0.0;	/* just avoid compiler 'unused' warnings */
3030 #endif
3031 }
3032