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