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