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