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