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