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