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