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