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