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