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