1 /* 2 * Copyright (c) 2019-2022 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 handles 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 setNumaDomain(work->index); 1479 pthread_mutex_lock(&WorkerMutex); 1480 1481 while (work->terminate == 0) { 1482 dowait = 1; 1483 1484 switch(work->state) { 1485 case WORKER_IDLE: 1486 break; 1487 case WORKER_PENDING: 1488 /* 1489 * Fork the management process for the pkg operation 1490 * on this worker slot. 1491 * 1492 * This process will set up the environment, do the 1493 * mounts, will become the reaper, and will process 1494 * pipe commands and handle chroot operations. 1495 * 1496 * NOTE: If SOCK_CLOEXEC is not supported WorkerMutex 1497 * is sufficient to interlock F_SETFD FD_CLOEXEC 1498 * operations. 1499 */ 1500 ddassert(work->pkg); 1501 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 1502 PF_UNSPEC, work->fds)) { 1503 dfatal_errno("socketpair() during worker fork"); 1504 } 1505 snprintf(slotbuf, sizeof(slotbuf), "%d", work->index); 1506 snprintf(fdbuf, sizeof(fdbuf), "3"); 1507 1508 /* 1509 * Pass global flags and add-in the DEBUGSTOP if 1510 * the package is flagged for debugging. 1511 */ 1512 flags = WorkerProcFlags; 1513 1514 if (work->pkg->flags & PKGF_DEBUGSTOP) 1515 flags |= WORKER_PROC_DEBUGSTOP; 1516 else 1517 flags &= ~WORKER_PROC_DEBUGSTOP; 1518 1519 if (PkgVersionPkgSuffix) 1520 flags |= WORKER_PROC_PKGV17; 1521 else 1522 flags &= ~WORKER_PROC_PKGV17; 1523 1524 snprintf(flagsbuf, sizeof(flagsbuf), "%d", flags); 1525 1526 /* 1527 * fds[0] - master 1528 * fds[1] - slave 1529 * 1530 * We pass the salve descriptor in fd 3 and close all 1531 * other descriptors for security. 1532 */ 1533 pthread_mutex_unlock(&WorkerMutex); 1534 pid = vfork(); 1535 if (pid == 0) { 1536 close(work->fds[0]); 1537 dup2(work->fds[1], 3); 1538 closefrom(4); 1539 fcntl(3, F_SETFD, 0); 1540 execle(DSynthExecPath, DSynthExecPath, 1541 "-p", Profile, 1542 "WORKER", slotbuf, fdbuf, 1543 work->pkg->portdir, work->pkg->pkgfile, 1544 flagsbuf, 1545 NULL, envary); 1546 write(2, "EXECLE FAILURE\n", 15); 1547 _exit(1); 1548 } 1549 pthread_mutex_lock(&WorkerMutex); 1550 close(work->fds[1]); 1551 work->phase = PHASE_PENDING; 1552 work->lines = 0; 1553 work->memuse = 0; 1554 work->pid = pid; 1555 work->state = WORKER_RUNNING; 1556 /* fall through */ 1557 case WORKER_RUNNING: 1558 /* 1559 * Poll for status updates, if NULL is returned 1560 * and status is non-zero, the communications link 1561 * failed unexpectedly. 1562 */ 1563 pkg = work->pkg; 1564 pthread_mutex_unlock(&WorkerMutex); 1565 status = ipcreadmsg(work->fds[0], &wmsg); 1566 pthread_mutex_lock(&WorkerMutex); 1567 1568 if (status == 0) { 1569 /* 1570 * Normal message, can include normal 1571 * termination which changes us over 1572 * to another state. 1573 */ 1574 dowait = 0; 1575 switch(wmsg.cmd) { 1576 case WMSG_CMD_INSTALL_PKGS: 1577 wmsg.cmd = WMSG_RES_INSTALL_PKGS; 1578 wmsg.status = childInstallPkgDeps(work); 1579 pthread_mutex_unlock(&WorkerMutex); 1580 ipcwritemsg(work->fds[0], &wmsg); 1581 pthread_mutex_lock(&WorkerMutex); 1582 break; 1583 case WMSG_CMD_STATUS_UPDATE: 1584 work->phase = wmsg.phase; 1585 work->lines = wmsg.lines; 1586 if (work->memuse != wmsg.memuse) { 1587 RunningPkgDepSize += 1588 wmsg.memuse - work->memuse; 1589 work->memuse = wmsg.memuse; 1590 } 1591 break; 1592 case WMSG_CMD_SUCCESS: 1593 work->flags |= WORKERF_SUCCESS; 1594 break; 1595 case WMSG_CMD_FAILURE: 1596 work->flags |= WORKERF_FAILURE; 1597 break; 1598 case WMSG_CMD_FREEZEWORKER: 1599 work->flags |= WORKERF_FREEZE; 1600 break; 1601 default: 1602 break; 1603 } 1604 RunStatsUpdate(work, NULL); 1605 RunStatsSync(); 1606 } else { 1607 close(work->fds[0]); 1608 pthread_mutex_unlock(&WorkerMutex); 1609 while (waitpid(work->pid, &status, 0) < 0 && 1610 errno == EINTR) { 1611 ; 1612 } 1613 pthread_mutex_lock(&WorkerMutex); 1614 1615 if (work->flags & WORKERF_SUCCESS) { 1616 pkg->flags |= PKGF_SUCCESS; 1617 work->state = WORKER_DONE; 1618 } else if (work->flags & WORKERF_FAILURE) { 1619 pkg->flags |= PKGF_FAILURE; 1620 work->state = WORKER_DONE; 1621 } else { 1622 pkg->flags |= PKGF_FAILURE; 1623 work->state = WORKER_FAILED; 1624 } 1625 work->flags |= WORKERF_STATUS_UPDATE; 1626 pthread_cond_signal(&WorkerCond); 1627 } 1628 break; 1629 case WORKER_DONE: 1630 /* 1631 * pkg remains attached until frontend processes the 1632 * completion. The frontend will then set the state 1633 * back to idle. 1634 */ 1635 break; 1636 case WORKER_FAILED: 1637 /* 1638 * A worker failure means that the worker did not 1639 * send us a WMSG_CMD_SUCCESS or WMSG_CMD_FAILURE 1640 * ipc before terminating. 1641 * 1642 * We just sit in this state until the front-end 1643 * does something about it. 1644 */ 1645 break; 1646 case WORKER_FROZEN: 1647 /* 1648 * A worker getting frozen is debug-related. We 1649 * just sit in this state (likely forever). 1650 */ 1651 break; 1652 default: 1653 dfatal("worker: [%03d] Unexpected state %d " 1654 "for worker %d", 1655 work->index, work->state, work->index); 1656 /* NOT REACHED */ 1657 break; 1658 } 1659 1660 /* 1661 * The dsynth frontend will poll us approximately once 1662 * a second (its variable). 1663 */ 1664 if (dowait) 1665 pthread_cond_wait(&work->cond, &WorkerMutex); 1666 } 1667 1668 /* 1669 * Scrap the comm socket if running, this should cause the worker 1670 * process to kill its sub-programs and cleanup. 1671 */ 1672 if (work->state == WORKER_RUNNING) { 1673 pthread_mutex_unlock(&WorkerMutex); 1674 close(work->fds[0]); 1675 while (waitpid(work->pid, &status, 0) < 0 && 1676 errno == EINTR); 1677 pthread_mutex_lock(&WorkerMutex); 1678 } 1679 1680 /* 1681 * Final handshake 1682 */ 1683 work->state = WORKER_EXITING; 1684 pthread_cond_signal(&WorkerCond); 1685 pthread_mutex_unlock(&WorkerMutex); 1686 1687 return NULL; 1688 } 1689 1690 /* 1691 * Install all the binary packages (we have already built them) that 1692 * the current work package depends on, without duplicates, in a script 1693 * which will be run from within the specified work jail. 1694 * 1695 * Locked by WorkerMutex (global) 1696 */ 1697 static int 1698 childInstallPkgDeps(worker_t *work) 1699 { 1700 char *buf; 1701 FILE *fp; 1702 1703 if (PKGLIST_EMPTY(&work->pkg->idepon_list)) 1704 return 0; 1705 1706 asprintf(&buf, "%s/tmp/dsynth_install_pkgs", work->basedir); 1707 fp = fopen(buf, "w"); 1708 ddassert(fp != NULL); 1709 fprintf(fp, "#!/bin/sh\n"); 1710 fprintf(fp, "#\n"); 1711 fchmod(fileno(fp), 0755); 1712 1713 childInstallPkgDeps_recurse(fp, &work->pkg->idepon_list, 0, 1, 0); 1714 childInstallPkgDeps_recurse(fp, &work->pkg->idepon_list, 1, 1, 0); 1715 fprintf(fp, "\nexit 0\n"); 1716 fclose(fp); 1717 freestrp(&buf); 1718 1719 return 1; 1720 } 1721 1722 /* 1723 * Recursive child install dependencies. 1724 * 1725 * first_one_only is only specified if the pkg the list comes from 1726 * is a generic unflavored package that has flavors, telling us to 1727 * dive the first flavor only. 1728 * 1729 * However, in nearly all cases this flag will now be zero because 1730 * this code now dives the first flavor when encountering a dummy node 1731 * and clears nfirst on success. Hence if you are asking why 'nfirst' 1732 * is set to 1, and then zero, instead of just being removed entirely, 1733 * it is because there might still be an edge case here. 1734 */ 1735 static size_t 1736 childInstallPkgDeps_recurse(FILE *fp, pkglink_t *list, int undoit, 1737 int depth, int first_one_only) 1738 { 1739 pkglink_t *link; 1740 pkg_t *pkg; 1741 size_t tot = 0; 1742 int ndepth; 1743 int nfirst; 1744 1745 PKGLIST_FOREACH(link, list) { 1746 pkg = link->pkg; 1747 1748 /* 1749 * We don't want to mess up our depth test just below if 1750 * a DUMMY node had to be inserted. The nodes under the 1751 * dummy node. 1752 * 1753 * The elements under a dummy node represent all the flabor, 1754 * a dependency that directly references a dummy node only 1755 * uses the first flavor (first_one_only / nfirst). 1756 */ 1757 ndepth = (pkg->flags & PKGF_DUMMY) ? depth : depth + 1; 1758 nfirst = (pkg->flags & PKGF_DUMMY) ? 1 : 0; 1759 1760 /* 1761 * We only need all packages for the top-level dependencies. 1762 * The deeper ones only need DEP_TYPE_LIB and DEP_TYPE_RUN 1763 * (types greater than DEP_TYPE_BUILD) since they are already 1764 * built. 1765 */ 1766 if (depth > 1 && link->dep_type <= DEP_TYPE_BUILD) { 1767 if (first_one_only) 1768 break; 1769 continue; 1770 } 1771 1772 /* 1773 * If this is a dummy node with no package, the originator 1774 * is requesting a flavored package. We select the default 1775 * flavor which we presume is the first one. 1776 */ 1777 if (pkg->pkgfile == NULL && (pkg->flags & PKGF_DUMMY)) { 1778 pkg_t *spkg = pkg->idepon_list.next->pkg; 1779 1780 if (spkg) { 1781 if (fp) { 1782 fprintf(fp, 1783 "echo 'UNFLAVORED %s -> use " 1784 "%s'\n", 1785 pkg->portdir, 1786 spkg->portdir); 1787 } 1788 pkg = spkg; 1789 nfirst = 0; 1790 } else { 1791 if (fp) { 1792 fprintf(fp, 1793 "echo 'CANNOT FIND DEFAULT " 1794 "FLAVOR FOR %s'\n", 1795 pkg->portdir); 1796 } 1797 } 1798 } 1799 1800 if (undoit) { 1801 if (pkg->dsynth_install_flg == 1) { 1802 pkg->dsynth_install_flg = 0; 1803 tot += childInstallPkgDeps_recurse(fp, 1804 &pkg->idepon_list, 1805 undoit, 1806 ndepth, nfirst); 1807 } 1808 if (first_one_only) 1809 break; 1810 continue; 1811 } 1812 1813 if (pkg->dsynth_install_flg) { 1814 if (DebugOpt >= 2 && pkg->pkgfile && fp) { 1815 fprintf(fp, "echo 'AlreadyHave %s'\n", 1816 pkg->pkgfile); 1817 } 1818 if (first_one_only) 1819 break; 1820 continue; 1821 } 1822 1823 tot += childInstallPkgDeps_recurse(fp, &pkg->idepon_list, 1824 undoit, ndepth, nfirst); 1825 if (pkg->dsynth_install_flg) { 1826 if (first_one_only) 1827 break; 1828 continue; 1829 } 1830 pkg->dsynth_install_flg = 1; 1831 1832 /* 1833 * Generate package installation command 1834 */ 1835 if (fp && pkg->pkgfile) { 1836 fprintf(fp, "echo 'Installing /packages/All/%s'\n", 1837 pkg->pkgfile); 1838 fprintf(fp, "pkg install -q -U -y /packages/All/%s " 1839 "|| exit 1\n", 1840 pkg->pkgfile); 1841 } else if (fp) { 1842 fprintf(fp, "echo 'CANNOT FIND PKG FOR %s'\n", 1843 pkg->portdir); 1844 } 1845 1846 if (pkg->pkgfile) { 1847 struct stat st; 1848 char *path; 1849 char *ptr; 1850 1851 asprintf(&path, "%s/%s", RepositoryPath, pkg->pkgfile); 1852 ptr = strrchr(pkg->pkgfile, '.'); 1853 if (stat(path, &st) == 0) { 1854 if (strcmp(ptr, ".tar") == 0) 1855 tot += st.st_size; 1856 else if (strcmp(ptr, ".tgz") == 0) 1857 tot += st.st_size * 3; 1858 else if (strcmp(ptr, ".txz") == 0) 1859 tot += st.st_size * 5; 1860 else if (strcmp(ptr, ".tzst") == 0) 1861 tot += st.st_size * 5; 1862 else if (strcmp(ptr, ".tbz") == 0) 1863 tot += st.st_size * 3; 1864 else 1865 tot += st.st_size * 2; 1866 } 1867 free(path); 1868 } 1869 if (first_one_only) 1870 break; 1871 } 1872 return tot; 1873 } 1874 1875 /* 1876 * Worker process interactions. 1877 * 1878 * The worker process is responsible for managing the build of a single 1879 * package. It is exec'd by the master dsynth and only loads the 1880 * configuration. 1881 * 1882 * This process does not run in the chroot. It will become the reaper for 1883 * all sub-processes and it will enter the chroot to execute various phases. 1884 * It catches SIGINTR, SIGHUP, and SIGPIPE and will iterate, terminate, and 1885 * reap all sub-process upon kill or exit. 1886 * 1887 * The command line forwarded to this function is: 1888 * 1889 * WORKER slot# socketfd portdir/subdir 1890 * 1891 * TERM=dumb 1892 * USER=root 1893 * HOME=/root 1894 * LANG=C 1895 * SSL_NO_VERIFY_PEER=1 1896 * USE_PACKAGE_DEPENDS_ONLY=1 1897 * PORTSDIR=/xports 1898 * PORT_DBDIR=/options For ports options 1899 * PACKAGE_BUILDING=yes Don't build packages that aren't legally 1900 * buildable for a binary repo. 1901 * PKG_DBDIR=/var/db/pkg 1902 * PKG_CACHEDIR=/var/cache/pkg 1903 * PKG_CREATE_VERBOSE=yes Ensure periodic output during packaging 1904 * (custom environment) 1905 * PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin 1906 * UNAME_s=DragonFly (example) 1907 * UNAME_v=DragonFly 5.7-SYNTH (example) 1908 * UNAME_p=x86_64 (example) 1909 * UNAME_m=x86_64 (example) 1910 * UNAME_r=5.7-SYNTH (example) 1911 * NO_DEPENDS=yes (conditional based on phase) 1912 * DISTDIR=/distfiles 1913 * WRKDIRPREFIX=/construction 1914 * BATCH=yes 1915 * MAKE_JOBS_NUMBER=n 1916 * 1917 * SETUP: 1918 * ldconfig -R 1919 * /usr/local/sbin/pkg-static install /packages/All/<the pkg pkg> 1920 * /usr/local/sbin/pkg-static install /packages/All/<pkg> 1921 * (for all dependencies) 1922 * 1923 * PHASES: make -C path FLAVOR=flavor <phase> 1924 * check-sanity 1925 * pkg-depends 1926 * fetch-depends 1927 * fetch 1928 * checksum 1929 * extract-depends 1930 * extract 1931 * patch-depends 1932 * patch 1933 * build-depends 1934 * lib-depends 1935 * configure 1936 * build 1937 * run-depends 1938 * stage 1939 * test (skipped) 1940 * check-plist ('dsynth test blahblah' or 'dsynth -D everything' only) 1941 * package e.g. /construction/lang/perl5.28/pkg/perl5-5.28.2.txz 1942 * install (skipped) 1943 * deinstall (skipped) 1944 */ 1945 void 1946 WorkerProcess(int ac, char **av) 1947 { 1948 wmsg_t wmsg; 1949 int fd; 1950 int slot; 1951 int tmpfd; 1952 int pkgpkg = 0; 1953 int status; 1954 int len; 1955 int do_install_phase; 1956 char *portdir; 1957 char *pkgfile; 1958 char *flavor; 1959 char *buf; 1960 worker_t *work; 1961 bulk_t *bulk; 1962 pkg_t pkg; 1963 buildenv_t *benv; 1964 FILE *fp; 1965 1966 /* 1967 * Parse arguments 1968 */ 1969 if (ac != 6) { 1970 dlog(DLOG_ALL, "WORKER PROCESS %d- bad arguments\n", getpid()); 1971 exit(1); 1972 } 1973 slot = strtol(av[1], NULL, 0); 1974 setNumaDomain(slot); 1975 1976 fd = strtol(av[2], NULL, 0); /* master<->slave messaging */ 1977 portdir = av[3]; 1978 pkgfile = av[4]; 1979 1980 flavor = strchr(portdir, '@'); 1981 if (flavor) { 1982 *flavor++ = 0; 1983 asprintf(&buf, "@%s", flavor); 1984 WorkerFlavorPrt = buf; 1985 buf = NULL; /* safety */ 1986 } 1987 WorkerProcFlags = strtol(av[5], NULL, 0); 1988 1989 if (WorkerProcFlags & WORKER_PROC_FETCHONLY) 1990 FetchOnlyOpt = 1; 1991 if (WorkerProcFlags & WORKER_PROC_PKGV17) 1992 PkgVersionPkgSuffix = 1; 1993 1994 bzero(&wmsg, sizeof(wmsg)); 1995 1996 setproctitle("[%02d] WORKER STARTUP %s%s", 1997 slot, portdir, WorkerFlavorPrt); 1998 1999 if (strcmp(portdir, "ports-mgmt/pkg") == 0) 2000 pkgpkg = 1; 2001 2002 signal(SIGTERM, phaseTerminateSignal); 2003 signal(SIGINT, phaseTerminateSignal); 2004 signal(SIGHUP, phaseTerminateSignal); 2005 2006 /* 2007 * Set up the environment 2008 */ 2009 setenv("TERM", "dumb", 1); 2010 setenv("USER", "root", 1); 2011 setenv("HOME", "/root", 1); 2012 setenv("LANG", "C", 1); 2013 setenv("SSL_NO_VERIFY_PEER", "1", 1); 2014 2015 /* 2016 * NOTE: PKG_SUFX - pkg versions older than 1.17 2017 * PKG_COMPRESSION_FORMAT - pkg versions >= 1.17 2018 * 2019 * Avoid WARNING messages in the logs by omitting 2020 * PKG_SUFX when we know the pkg version is >= 1.17. 2021 */ 2022 addbuildenv("USE_PACKAGE_DEPENDS_ONLY", "yes", BENV_MAKECONF); 2023 addbuildenv("PORTSDIR", "/xports", BENV_MAKECONF); 2024 addbuildenv("PORT_DBDIR", "/options", BENV_MAKECONF); 2025 addbuildenv("PKG_DBDIR", "/var/db/pkg", BENV_MAKECONF); 2026 addbuildenv("PKG_CACHEDIR", "/var/cache/pkg", BENV_MAKECONF); 2027 addbuildenv("PKG_COMPRESSION_FORMAT", UsePkgSufx, BENV_MAKECONF); 2028 if (PkgVersionPkgSuffix == 0) 2029 addbuildenv("PKG_SUFX", UsePkgSufx, BENV_MAKECONF); 2030 2031 /* 2032 * We are exec'ing the worker process so various bits of global 2033 * state that we want to inherit have to be passed in. 2034 */ 2035 if (WorkerProcFlags & WORKER_PROC_DEVELOPER) 2036 addbuildenv("DEVELOPER", "1", BENV_MAKECONF); 2037 2038 /* 2039 * CCache is a horrible unreliable hack but... leave the 2040 * mechanism in-place in case someone has a death wish. 2041 */ 2042 if (UseCCache) { 2043 addbuildenv("WITH_CCACHE_BUILD", "yes", BENV_MAKECONF); 2044 addbuildenv("CCACHE_DIR", "/ccache", BENV_MAKECONF); 2045 } 2046 2047 addbuildenv("UID", "0", BENV_MAKECONF); 2048 addbuildenv("ARCH", ArchitectureName, BENV_MAKECONF); 2049 2050 /* 2051 * Always honor either the operating system detection or the 2052 * operating system selection in the config file. 2053 */ 2054 addbuildenv("OPSYS", OperatingSystemName, BENV_MAKECONF); 2055 2056 #ifdef __DragonFly__ 2057 addbuildenv("DFLYVERSION", VersionFromParamHeader, BENV_MAKECONF); 2058 addbuildenv("OSVERSION", "9999999", BENV_MAKECONF); 2059 #else 2060 #error "Need OS-specific data to generate make.conf" 2061 #endif 2062 2063 addbuildenv("OSREL", ReleaseName, BENV_MAKECONF); 2064 addbuildenv("_OSRELEASE", VersionOnlyName, BENV_MAKECONF); 2065 2066 setenv("PATH", 2067 "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", 2068 1); 2069 2070 setenv("UNAME_s", OperatingSystemName, 1); 2071 setenv("UNAME_v", VersionName, 1); 2072 setenv("UNAME_p", ArchitectureName, 1); 2073 setenv("UNAME_m", MachineName, 1); 2074 setenv("UNAME_r", ReleaseName, 1); 2075 2076 addbuildenv("DISTDIR", "/distfiles", BENV_MAKECONF); 2077 addbuildenv("WRKDIRPREFIX", "/construction", BENV_MAKECONF); 2078 addbuildenv("BATCH", "yes", BENV_MAKECONF); 2079 2080 /* 2081 * Special consideration 2082 * 2083 * PACKAGE_BUILDING - Disallow packaging ports which do not allow 2084 * for binary distribution. 2085 * 2086 * PKG_CREATE_VERBOSE - Ensure periodic output during the packaging 2087 * process to avoid a watchdog timeout. 2088 * 2089 */ 2090 addbuildenv("PACKAGE_BUILDING", "yes", BENV_MAKECONF); 2091 addbuildenv("PKG_CREATE_VERBOSE", "yes", BENV_MAKECONF); 2092 asprintf(&buf, "%d", MaxJobs); 2093 addbuildenv("MAKE_JOBS_NUMBER", buf, BENV_MAKECONF); 2094 freestrp(&buf); 2095 2096 if (flavor) 2097 setenv("FLAVOR", flavor, 1); 2098 2099 /* 2100 * Become the reaper 2101 */ 2102 if (procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL) < 0) 2103 dfatal_errno("procctl() - Cannot become reaper"); 2104 2105 /* 2106 * Initialize a worker structure 2107 */ 2108 DoInitBuild(slot); 2109 2110 bzero(&pkg, sizeof(pkg)); 2111 pkg.portdir = portdir; /* sans flavor */ 2112 pkg.pkgfile = pkgfile; 2113 if (strchr(portdir, '/')) 2114 len = strchr(portdir, '/') - portdir; 2115 else 2116 len = 0; 2117 2118 /* 2119 * Setup the logfile 2120 */ 2121 asprintf(&pkg.logfile, 2122 "%s/%*.*s___%s%s%s.log", 2123 LogsPath, len, len, portdir, 2124 ((portdir[len] == '/') ? portdir + len + 1 : portdir + len), 2125 (flavor ? "@" : ""), 2126 (flavor ? flavor : "")); 2127 tmpfd = open(pkg.logfile, O_RDWR|O_CREAT|O_TRUNC, 0666); 2128 if (tmpfd >= 0) { 2129 if (DebugOpt >= 2) { 2130 dlog(DLOG_ALL, "[%03d] %s LOGFILE %s\n", 2131 slot, pkg.portdir, pkg.logfile); 2132 } 2133 close(tmpfd); 2134 } else { 2135 dlog(DLOG_ALL, "[%03d] LOGFILE %s (create failed)\n", 2136 slot, pkg.logfile); 2137 } 2138 2139 /* 2140 * Setup the work structure. Because this is an exec'd sub-process, 2141 * there is only one work structure. 2142 */ 2143 work = &WorkerAry[0]; 2144 work->flavor = flavor; 2145 work->fds[0] = fd; 2146 work->pkg = &pkg; 2147 work->start_time = time(NULL); 2148 2149 /* 2150 * Do mounts 2151 */ 2152 SigWork = work; 2153 setproctitle("[%02d] WORKER MOUNTS %s%s", 2154 slot, portdir, WorkerFlavorPrt); 2155 DoWorkerMounts(work); 2156 2157 /* 2158 * Generate an /etc/make.conf in the build base 2159 */ 2160 asprintf(&buf, "%s/etc/make.conf", work->basedir); 2161 fp = fopen(buf, "w"); 2162 dassert_errno(fp, "Unable to create %s\n", buf); 2163 for (benv = BuildEnv; benv; benv = benv->next) { 2164 if (benv->type & BENV_PKGLIST) 2165 continue; 2166 if ((benv->type & BENV_CMDMASK) == BENV_MAKECONF) { 2167 if (DebugOpt >= 2) { 2168 dlog(DLOG_ALL, "[%03d] ENV %s=%s\n", 2169 slot, benv->label, benv->data); 2170 } 2171 fprintf(fp, "%s=%s\n", benv->label, benv->data); 2172 } 2173 } 2174 fclose(fp); 2175 freestrp(&buf); 2176 2177 /* 2178 * Set up our hooks 2179 */ 2180 if (UsingHooks) 2181 initbulk(childHookRun, MaxBulk); 2182 2183 /* 2184 * Start phases 2185 */ 2186 wmsg.cmd = WMSG_CMD_INSTALL_PKGS; 2187 ipcwritemsg(fd, &wmsg); 2188 status = ipcreadmsg(fd, &wmsg); 2189 if (status < 0 || wmsg.cmd != WMSG_RES_INSTALL_PKGS) 2190 dfatal("pkg installation handshake failed"); 2191 do_install_phase = wmsg.status; 2192 if (FetchOnlyOpt) 2193 do_install_phase = 0; 2194 2195 wmsg.cmd = WMSG_CMD_STATUS_UPDATE; 2196 wmsg.phase = PHASE_INSTALL_PKGS; 2197 wmsg.lines = 0; 2198 2199 status = ipcwritemsg(fd, &wmsg); 2200 2201 if (pkgpkg && FetchOnlyOpt == 0) { 2202 dophase(work, &wmsg, 2203 WDOG5, PHASE_PACKAGE, "package"); 2204 } else { 2205 /* 2206 * Dump as much information of the build process as possible. 2207 * Will help troubleshooting port build breakages. 2208 * Only enabled when DEVELOPER is set. 2209 * 2210 * This sort of mimics what synth did. 2211 */ 2212 if (WorkerProcFlags & WORKER_PROC_DEVELOPER) { 2213 dophase(work, &wmsg, 2214 WDOG2, PHASE_DUMP_ENV, "Environment"); 2215 dophase(work, &wmsg, 2216 WDOG2, PHASE_SHOW_CONFIG, "showconfig"); 2217 dophase(work, &wmsg, 2218 WDOG2, PHASE_DUMP_VAR, "CONFIGURE_ENV"); 2219 dophase(work, &wmsg, 2220 WDOG2, PHASE_DUMP_VAR, "CONFIGURE_ARGS"); 2221 dophase(work, &wmsg, 2222 WDOG2, PHASE_DUMP_VAR, "MAKE_ENV"); 2223 dophase(work, &wmsg, 2224 WDOG2, PHASE_DUMP_VAR, "MAKE_ARGS"); 2225 dophase(work, &wmsg, 2226 WDOG2, PHASE_DUMP_VAR, "PLIST_SUB"); 2227 dophase(work, &wmsg, 2228 WDOG2, PHASE_DUMP_VAR, "SUB_LIST"); 2229 dophase(work, &wmsg, 2230 WDOG2, PHASE_DUMP_MAKECONF, "/etc/make.conf"); 2231 } 2232 2233 if (do_install_phase) { 2234 dophase(work, &wmsg, 2235 WDOG4, PHASE_INSTALL_PKGS, "setup"); 2236 } 2237 dophase(work, &wmsg, 2238 WDOG2, PHASE_CHECK_SANITY, "check-sanity"); 2239 if (FetchOnlyOpt == 0) { 2240 dophase(work, &wmsg, 2241 WDOG2, PHASE_PKG_DEPENDS, "pkg-depends"); 2242 } 2243 dophase(work, &wmsg, 2244 WDOG7, PHASE_FETCH_DEPENDS, "fetch-depends"); 2245 dophase(work, &wmsg, 2246 WDOG7, PHASE_FETCH, "fetch"); 2247 dophase(work, &wmsg, 2248 WDOG2, PHASE_CHECKSUM, "checksum"); 2249 if (FetchOnlyOpt == 0) { 2250 dophase(work, &wmsg, 2251 WDOG3, PHASE_EXTRACT_DEPENDS, "extract-depends"); 2252 dophase(work, &wmsg, 2253 WDOG3, PHASE_EXTRACT, "extract"); 2254 dophase(work, &wmsg, 2255 WDOG2, PHASE_PATCH_DEPENDS, "patch-depends"); 2256 dophase(work, &wmsg, 2257 WDOG2, PHASE_PATCH, "patch"); 2258 dophase(work, &wmsg, 2259 WDOG5, PHASE_BUILD_DEPENDS, "build-depends"); 2260 dophase(work, &wmsg, 2261 WDOG5, PHASE_LIB_DEPENDS, "lib-depends"); 2262 dophase(work, &wmsg, 2263 WDOG3, PHASE_CONFIGURE, "configure"); 2264 dophase(work, &wmsg, 2265 WDOG9, PHASE_BUILD, "build"); 2266 dophase(work, &wmsg, 2267 WDOG5, PHASE_RUN_DEPENDS, "run-depends"); 2268 dophase(work, &wmsg, 2269 WDOG5, PHASE_STAGE, "stage"); 2270 #if 0 2271 dophase(work, &wmsg, 2272 WDOG5, PHASE_TEST, "test"); 2273 #endif 2274 if (WorkerProcFlags & WORKER_PROC_CHECK_PLIST) { 2275 dophase(work, &wmsg, 2276 WDOG1, PHASE_CHECK_PLIST, "check-plist"); 2277 } 2278 dophase(work, &wmsg, 2279 WDOG5, PHASE_PACKAGE, "package"); 2280 2281 if (WorkerProcFlags & WORKER_PROC_INSTALL) { 2282 dophase(work, &wmsg, 2283 WDOG5, PHASE_INSTALL, "install"); 2284 } 2285 2286 if (WorkerProcFlags & WORKER_PROC_DEINSTALL) { 2287 dophase(work, &wmsg, 2288 WDOG5, PHASE_DEINSTALL, "deinstall"); 2289 } 2290 } 2291 } 2292 2293 if (MasterPtyFd >= 0) { 2294 close(MasterPtyFd); 2295 MasterPtyFd = -1; 2296 } 2297 2298 setproctitle("[%02d] WORKER CLEANUP %s%s", 2299 slot, portdir, WorkerFlavorPrt); 2300 2301 /* 2302 * Copy the package to the repo. 2303 */ 2304 if (work->accum_error == 0 && FetchOnlyOpt == 0) { 2305 char *b1; 2306 char *b2; 2307 2308 asprintf(&b1, "%s/construction/%s/pkg/%s", 2309 work->basedir, pkg.portdir, pkg.pkgfile); 2310 asprintf(&b2, "%s/%s", RepositoryPath, pkg.pkgfile); 2311 if (copyfile(b1, b2)) { 2312 ++work->accum_error; 2313 dlog(DLOG_ALL, "[%03d] %s Unable to copy %s to %s\n", 2314 work->index, pkg.portdir, b1, b2); 2315 } 2316 free(b1); 2317 free(b2); 2318 } 2319 2320 /* 2321 * Unmount, unless we are in DebugStopMode. 2322 */ 2323 if ((WorkerProcFlags & WORKER_PROC_DEBUGSTOP) == 0) 2324 DoWorkerUnmounts(work); 2325 2326 /* 2327 * Send completion status to master dsynth worker thread. 2328 */ 2329 if (work->accum_error) { 2330 wmsg.cmd = WMSG_CMD_FAILURE; 2331 } else { 2332 wmsg.cmd = WMSG_CMD_SUCCESS; 2333 } 2334 ipcwritemsg(fd, &wmsg); 2335 if (WorkerProcFlags & WORKER_PROC_DEBUGSTOP) { 2336 wmsg.cmd = WMSG_CMD_FREEZEWORKER; 2337 ipcwritemsg(fd, &wmsg); 2338 } 2339 if (UsingHooks) { 2340 while ((bulk = getbulk()) != NULL) 2341 freebulk(bulk); 2342 donebulk(); 2343 } 2344 } 2345 2346 static int 2347 check_dns(void) 2348 { 2349 char check_domains[4][24] = { 2350 "www.dragonflybsd.org", 2351 "www.freebsd.org", 2352 "www.openbsd.org", 2353 "www.netbsd.org", 2354 }; 2355 int failures = 0; 2356 2357 for (int i = 0; i < 4; i++) 2358 if (gethostbyname (check_domains[i]) == NULL) 2359 failures++; 2360 if (failures > 1) 2361 return -1; 2362 2363 return 0; 2364 } 2365 2366 static void 2367 dophase(worker_t *work, wmsg_t *wmsg, int wdog, int phaseid, const char *phase) 2368 { 2369 pkg_t *pkg = work->pkg; 2370 char buf[1024]; 2371 pid_t pid; 2372 int status; 2373 int ms; 2374 pid_t wpid; 2375 int wpid_reaped; 2376 int fdlog; 2377 time_t start_time; 2378 time_t last_time; 2379 time_t next_time; 2380 time_t wdog_time; 2381 FILE *fp; 2382 2383 if (work->accum_error) 2384 return; 2385 setproctitle("[%02d] WORKER %-8.8s %s%s", 2386 work->index, phase, pkg->portdir, WorkerFlavorPrt); 2387 wmsg->phase = phaseid; 2388 if (ipcwritemsg(work->fds[0], wmsg) < 0) { 2389 dlog(DLOG_ALL, "[%03d] %s Lost Communication with dsynth, " 2390 "aborting worker\n", 2391 work->index, pkg->portdir); 2392 ++work->accum_error; 2393 return; 2394 } 2395 2396 /* 2397 * Execute the port make command in chroot on a pty. 2398 */ 2399 fflush(stdout); 2400 fflush(stderr); 2401 if (MasterPtyFd >= 0) { 2402 int slavefd; 2403 2404 /* 2405 * NOTE: We can't open the slave in the child because the 2406 * master may race a disconnection test. If we open 2407 * it in the parent our close() will flush any pending 2408 * output not read by the master (which is the same 2409 * parent process) and deadlock. 2410 * 2411 * Solve this by hand-shaking the slave tty to give 2412 * the master time to close its slavefd (after this 2413 * section). 2414 * 2415 * Leave the tty defaults intact, which also likely 2416 * means it will be in line-buffered mode, so handshake 2417 * with a full line. 2418 * 2419 * TODO: Our handshake probably echos back to the master pty 2420 * due to tty echo, and ends up in the log, so just 2421 * pass through a newline. 2422 */ 2423 slavefd = open(ptsname(MasterPtyFd), O_RDWR); 2424 dassert_errno(slavefd >= 0, "Cannot open slave pty"); 2425 2426 /* 2427 * Now do the fork. 2428 */ 2429 pid = fork(); 2430 if (pid == 0) { 2431 login_tty(slavefd); 2432 /* login_tty() closes slavefd */ 2433 } else { 2434 close(slavefd); 2435 } 2436 } else { 2437 /* 2438 * Initial MasterPtyFd for the slot, just use forkpty(). 2439 */ 2440 pid = forkpty(&MasterPtyFd, NULL, NULL, NULL); 2441 } 2442 2443 /* 2444 * The slave must make sure the master has time to close slavefd 2445 * in the re-use case before going its merry way. The master needs 2446 * to set terminal modes and the window as well. 2447 */ 2448 if (pid == 0) { 2449 /* 2450 * Slave nices itself and waits for handshake 2451 */ 2452 char ttybuf[2]; 2453 2454 /* 2455 * Self-nice to be nice (ignore any error) 2456 */ 2457 if (NiceOpt) 2458 setpriority(PRIO_PROCESS, 0, NiceOpt); 2459 2460 read(0, ttybuf, 1); 2461 } else { 2462 /* 2463 * We are going through a pty, so set the tty modes to 2464 * Set tty modes so we do not get ^M's in the log files. 2465 * 2466 * This isn't fatal if it doesn't work. Remember that 2467 * our output goes through the pty to the management 2468 * process which will log it. 2469 */ 2470 struct termios tio; 2471 struct winsize win; 2472 2473 if (tcgetattr(MasterPtyFd, &tio) == 0) { 2474 tio.c_oflag |= OPOST | ONOCR; 2475 tio.c_oflag &= ~(OCRNL | ONLCR); 2476 tio.c_iflag |= ICRNL; 2477 tio.c_iflag &= ~(INLCR | IGNCR); 2478 if (tcsetattr(MasterPtyFd, TCSANOW, &tio)) { 2479 printf("tcsetattr failed: %s\n", 2480 strerror(errno)); 2481 } 2482 2483 /* 2484 * Give the tty a non-zero columns field. 2485 * This fixes at least one port (textproc/po4a) 2486 */ 2487 if (ioctl(MasterPtyFd, TIOCGWINSZ, &win) == 0) { 2488 win.ws_col = 80; 2489 ioctl(MasterPtyFd, TIOCSWINSZ, &win); 2490 } else { 2491 printf("TIOCGWINSZ failed: %s\n", 2492 strerror(errno)); 2493 } 2494 2495 } else { 2496 printf("tcgetattr failed: %s\n", strerror(errno)); 2497 } 2498 2499 /* 2500 * Master issues handshake 2501 */ 2502 write(MasterPtyFd, "\n", 1); 2503 } 2504 2505 if (pid == 0) { 2506 /* 2507 * Additional phase-specific environment variables 2508 * 2509 * - Do not try to process missing depends outside of the 2510 * depends phases. Also relies on USE_PACKAGE_DEPENDS_ONLY 2511 * in the make.conf. 2512 */ 2513 switch(phaseid) { 2514 case PHASE_CHECK_SANITY: 2515 case PHASE_FETCH: 2516 case PHASE_CHECKSUM: 2517 case PHASE_EXTRACT: 2518 case PHASE_PATCH: 2519 case PHASE_CONFIGURE: 2520 case PHASE_STAGE: 2521 case PHASE_TEST: 2522 case PHASE_CHECK_PLIST: 2523 case PHASE_INSTALL: 2524 case PHASE_DEINSTALL: 2525 break; 2526 case PHASE_PKG_DEPENDS: 2527 case PHASE_FETCH_DEPENDS: 2528 case PHASE_EXTRACT_DEPENDS: 2529 case PHASE_PATCH_DEPENDS: 2530 case PHASE_BUILD_DEPENDS: 2531 case PHASE_LIB_DEPENDS: 2532 case PHASE_RUN_DEPENDS: 2533 break; 2534 default: 2535 setenv("NO_DEPENDS", "1", 1); 2536 break; 2537 } 2538 2539 /* 2540 * Clean-up, chdir, and chroot. 2541 */ 2542 closefrom(3); 2543 if (chdir(work->basedir) < 0) 2544 dfatal_errno("chdir in phase initialization"); 2545 if (chroot(work->basedir) < 0) 2546 dfatal_errno("chroot in phase initialization"); 2547 2548 /* Explicitly fail when DNS is not working */ 2549 if (check_dns() != 0) 2550 dfatal("DNS resolution not working"); 2551 2552 /* 2553 * We have a choice here on how to handle stdin (fd 0). 2554 * We can leave it connected to the pty in which case 2555 * the build will just block if it tries to ask a 2556 * question (and the watchdog will kill it, eventually), 2557 * or we can try to EOF the pty, or we can attach /dev/null 2558 * to descriptor 0. 2559 */ 2560 if (NullStdinOpt) { 2561 int fd; 2562 2563 fd = open("/dev/null", O_RDWR); 2564 dassert_errno(fd >= 0, "cannot open /dev/null"); 2565 if (fd != 0) { 2566 dup2(fd, 0); 2567 close(fd); 2568 } 2569 } 2570 2571 /* 2572 * Execute the appropriate command. 2573 */ 2574 switch(phaseid) { 2575 case PHASE_INSTALL_PKGS: 2576 snprintf(buf, sizeof(buf), "/tmp/dsynth_install_pkgs"); 2577 execl(buf, buf, NULL); 2578 break; 2579 case PHASE_DUMP_ENV: 2580 snprintf(buf, sizeof(buf), "/usr/bin/env"); 2581 execl(buf, buf, NULL); 2582 break; 2583 case PHASE_DUMP_VAR: 2584 snprintf(buf, sizeof(buf), "/xports/%s", pkg->portdir); 2585 execl(MAKE_BINARY, MAKE_BINARY, "-C", buf, "-V", phase, 2586 NULL); 2587 break; 2588 case PHASE_DUMP_MAKECONF: 2589 snprintf(buf, sizeof(buf), "/bin/cat"); 2590 execl(buf, buf, "/etc/make.conf", NULL); 2591 break; 2592 case PHASE_SHOW_CONFIG: 2593 /* fall-through */ 2594 default: 2595 snprintf(buf, sizeof(buf), "/xports/%s", pkg->portdir); 2596 execl(MAKE_BINARY, MAKE_BINARY, "-C", buf, phase, NULL); 2597 break; 2598 } 2599 _exit(1); 2600 } 2601 fcntl(MasterPtyFd, F_SETFL, O_NONBLOCK); 2602 2603 if (pid < 0) { 2604 dlog(DLOG_ALL, "[%03d] %s Fork Failed: %s\n", 2605 work->index, pkg->logfile, strerror(errno)); 2606 ++work->accum_error; 2607 return; 2608 } 2609 2610 SigPid = pid; 2611 2612 fdlog = open(pkg->logfile, O_RDWR|O_CREAT|O_APPEND, 0644); 2613 if (fdlog < 0) { 2614 dlog(DLOG_ALL, "[%03d] %s Cannot open logfile '%s': %s\n", 2615 work->index, pkg->portdir, 2616 pkg->logfile, strerror(errno)); 2617 } 2618 2619 snprintf(buf, sizeof(buf), 2620 "----------------------------------------" 2621 "---------------------------------------\n" 2622 "-- Phase: %s\n" 2623 "----------------------------------------" 2624 "---------------------------------------\n", 2625 phase); 2626 write(fdlog, buf, strlen(buf)); 2627 2628 start_time = time(NULL); 2629 last_time = start_time; 2630 wdog_time = start_time; 2631 wpid_reaped = 0; 2632 2633 status = 0; 2634 for (;;) { 2635 ms = mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time); 2636 if (ms == MPTY_FAILED) { 2637 dlog(DLOG_ALL, 2638 "[%03d] %s lost pty in phase %s, terminating\n", 2639 work->index, pkg->portdir, phase); 2640 break; 2641 } 2642 if (ms == MPTY_EOF) 2643 break; 2644 2645 /* 2646 * Generally speaking update status once a second. 2647 * This also allows us to detect if the management 2648 * dsynth process has gone away. 2649 */ 2650 next_time = time(NULL); 2651 if (next_time != last_time) { 2652 double dload[3]; 2653 double dv; 2654 int wdog_scaled; 2655 2656 /* 2657 * Send status update to the worker management thread 2658 * in the master dsynth process. Remember, *WE* are 2659 * the worker management process sub-fork. 2660 */ 2661 if (ipcwritemsg(work->fds[0], wmsg) < 0) 2662 break; 2663 last_time = next_time; 2664 2665 /* 2666 * Watchdog scaling 2667 */ 2668 getloadavg(dload, 3); 2669 adjloadavg(dload); 2670 dv = dload[2] / NumCores; 2671 if (dv < (double)NumCores) { 2672 wdog_scaled = wdog; 2673 } else { 2674 if (dv > 4.0 * NumCores) 2675 dv = 4.0 * NumCores; 2676 wdog_scaled = wdog * dv / NumCores; 2677 } 2678 2679 /* 2680 * Watchdog 2681 */ 2682 if (next_time - wdog_time >= wdog_scaled * 60) { 2683 snprintf(buf, sizeof(buf), 2684 "\n--------\n" 2685 "WATCHDOG TIMEOUT FOR %s in %s " 2686 "after %d minutes\n" 2687 "Killing pid %d\n" 2688 "--------\n", 2689 pkg->portdir, phase, wdog_scaled, pid); 2690 if (fdlog >= 0) 2691 write(fdlog, buf, strlen(buf)); 2692 dlog(DLOG_ALL, 2693 "[%03d] %s WATCHDOG TIMEOUT in %s " 2694 "after %d minutes (%d min scaled)\n", 2695 work->index, pkg->portdir, phase, 2696 wdog, wdog_scaled); 2697 kill(pid, SIGKILL); 2698 ++work->accum_error; 2699 break; 2700 } 2701 } 2702 2703 /* 2704 * Check process exit. Normally the pty will EOF 2705 * but if background processes remain we need to 2706 * check here to see if our primary exec is done, 2707 * so we can break out and reap those processes. 2708 * 2709 * Generally reap any other processes we have inherited 2710 * while we are here. 2711 */ 2712 do { 2713 wpid = wait3(&status, WNOHANG, NULL); 2714 } while (wpid > 0 && wpid != pid); 2715 if (wpid == pid && WIFEXITED(status)) { 2716 wpid_reaped = 1; 2717 break; 2718 } 2719 } 2720 2721 next_time = time(NULL); 2722 2723 setproctitle("[%02d] WORKER EXITREAP %s%s", 2724 work->index, pkg->portdir, WorkerFlavorPrt); 2725 2726 /* 2727 * We usually get here due to a mpty EOF, but not always as there 2728 * could be persistent processes still holding the slave. Finish 2729 * up getting the exit status for the main process we are waiting 2730 * on and clean out any data left on the MasterPtyFd (as it could 2731 * be blocking the exit). 2732 */ 2733 while (wpid_reaped == 0) { 2734 (void)mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time); 2735 wpid = waitpid(pid, &status, WNOHANG); 2736 if (wpid == pid && WIFEXITED(status)) { 2737 wpid_reaped = 1; 2738 break; 2739 } 2740 if (wpid < 0 && errno != EINTR) { 2741 break; 2742 } 2743 2744 /* 2745 * Safety. The normal phase waits until the fork/exec'd 2746 * pid finishes, causing a pty EOF on exit (the slave 2747 * descriptor is closed by the kernel on exit so the 2748 * process should already have exited). 2749 * 2750 * However, it is also possible to get here if the pty fails 2751 * for some reason. In this case, make sure that the process 2752 * is killed. 2753 */ 2754 kill(pid, SIGKILL); 2755 } 2756 2757 /* 2758 * Clean out anything left on the pty but don't wait around 2759 * because there could be background processes preventing the 2760 * slave side from closing. 2761 */ 2762 while (mptylogpoll(MasterPtyFd, fdlog, wmsg, &wdog_time) == MPTY_DATA) 2763 ; 2764 2765 /* 2766 * Report on the exit condition. If the pid was somehow lost 2767 * (probably due to someone gdb'ing the process), assume an error. 2768 */ 2769 if (wpid_reaped) { 2770 if (WEXITSTATUS(status)) { 2771 dlog(DLOG_ALL | DLOG_FILTER, 2772 "[%03d] %s Build phase '%s' failed exit %d\n", 2773 work->index, pkg->portdir, phase, 2774 WEXITSTATUS(status)); 2775 ++work->accum_error; 2776 } 2777 } else { 2778 dlog(DLOG_ALL, "[%03d] %s Build phase '%s' failed - lost pid\n", 2779 work->index, pkg->portdir, phase); 2780 ++work->accum_error; 2781 } 2782 2783 /* 2784 * Kill any processes still running (sometimes processes end up in 2785 * the background during a dports build), and clean up any other 2786 * children that we have inherited. 2787 */ 2788 phaseReapAll(); 2789 2790 /* 2791 * After the extraction phase add the space used by /construction 2792 * to the memory use. This helps us reduce the amount of paging 2793 * we do due to extremely large package extractions (languages, 2794 * chromium, etc). 2795 * 2796 * (dsynth already estimated the space used by the package deps 2797 * up front, but this will help us further). 2798 */ 2799 if (work->accum_error == 0 && phaseid == PHASE_EXTRACT) { 2800 struct statfs sfs; 2801 char *b1; 2802 2803 asprintf(&b1, "%s/construction", work->basedir); 2804 if (statfs(b1, &sfs) == 0) { 2805 wmsg->memuse = (sfs.f_blocks - sfs.f_bfree) * 2806 sfs.f_bsize; 2807 ipcwritemsg(work->fds[0], wmsg); 2808 } 2809 } 2810 2811 /* 2812 * Update log 2813 */ 2814 if (fdlog >= 0) { 2815 struct stat st; 2816 int h; 2817 int m; 2818 int s; 2819 2820 last_time = next_time - start_time; 2821 s = last_time % 60; 2822 m = last_time / 60 % 60; 2823 h = last_time / 3600; 2824 2825 fp = fdopen(fdlog, "a"); 2826 if (fp == NULL) { 2827 dlog(DLOG_ALL, "[%03d] %s Cannot fdopen fdlog: %s %d\n", 2828 work->index, pkg->portdir, 2829 strerror(errno), fstat(fdlog, &st)); 2830 close(fdlog); 2831 goto skip; 2832 } 2833 2834 fprintf(fp, "\n"); 2835 if (work->accum_error) { 2836 fprintf(fp, "FAILED %02d:%02d:%02d\n", h, m, s); 2837 } else { 2838 if (phaseid == PHASE_EXTRACT && wmsg->memuse) { 2839 fprintf(fp, "Extracted Memory Use: %6.2fM\n", 2840 wmsg->memuse / (1024.0 * 1024.0)); 2841 } 2842 fprintf(fp, "SUCCEEDED %02d:%02d:%02d\n", h, m, s); 2843 } 2844 last_time = next_time - work->start_time; 2845 s = last_time % 60; 2846 m = last_time / 60 % 60; 2847 h = last_time / 3600; 2848 if (phaseid == PHASE_PACKAGE) { 2849 fprintf(fp, "TOTAL TIME %02d:%02d:%02d\n", h, m, s); 2850 } 2851 fprintf(fp, "\n"); 2852 fclose(fp); 2853 skip: 2854 ; 2855 } 2856 2857 } 2858 2859 static void 2860 phaseReapAll(void) 2861 { 2862 struct reaper_status rs; 2863 int status; 2864 2865 while (procctl(P_PID, getpid(), PROC_REAP_STATUS, &rs) == 0) { 2866 if ((rs.flags & PROC_REAP_ACQUIRE) == 0) 2867 break; 2868 if (rs.pid_head < 0) 2869 break; 2870 if (kill(rs.pid_head, SIGKILL) == 0) { 2871 while (waitpid(rs.pid_head, &status, 0) < 0) 2872 ; 2873 } 2874 } 2875 while (wait3(&status, 0, NULL) > 0) 2876 ; 2877 } 2878 2879 static void 2880 phaseTerminateSignal(int sig __unused) 2881 { 2882 if (CopyFileFd >= 0) 2883 close(CopyFileFd); 2884 if (MasterPtyFd >= 0) 2885 close(MasterPtyFd); 2886 if (SigPid > 1) 2887 kill(SigPid, SIGKILL); 2888 phaseReapAll(); 2889 if (SigWork) 2890 DoWorkerUnmounts(SigWork); 2891 exit(1); 2892 } 2893 2894 static 2895 char * 2896 buildskipreason(pkglink_t *parent, pkg_t *pkg) 2897 { 2898 pkglink_t *link; 2899 pkg_t *scan; 2900 char *reason = NULL; 2901 char *ptr; 2902 size_t tot; 2903 size_t len; 2904 pkglink_t stack; 2905 2906 if ((pkg->flags & PKGF_NOBUILD_I) && pkg->ignore) 2907 asprintf(&reason, "%s ", pkg->ignore); 2908 2909 tot = 0; 2910 PKGLIST_FOREACH(link, &pkg->idepon_list) { 2911 #if 0 2912 if (link->dep_type > DEP_TYPE_BUILD) 2913 continue; 2914 #endif 2915 scan = link->pkg; 2916 if (scan == NULL) 2917 continue; 2918 if ((scan->flags & (PKGF_ERROR | PKGF_NOBUILD)) == 0) 2919 continue; 2920 if (scan->flags & PKGF_NOBUILD) { 2921 stack.pkg = scan; 2922 stack.next = parent; 2923 ptr = buildskipreason(&stack, scan); 2924 len = strlen(scan->portdir) + strlen(ptr) + 8; 2925 reason = realloc(reason, tot + len); 2926 snprintf(reason + tot, len, "%s->%s", 2927 scan->portdir, ptr); 2928 free(ptr); 2929 } else { 2930 len = strlen(scan->portdir) + 8; 2931 reason = realloc(reason, tot + len); 2932 snprintf(reason + tot, len, "%s", scan->portdir); 2933 } 2934 2935 /* 2936 * Don't try to print the entire graph 2937 */ 2938 if (parent) 2939 break; 2940 tot += strlen(reason + tot); 2941 reason[tot++] = ' '; 2942 reason[tot] = 0; 2943 } 2944 return (reason); 2945 } 2946 2947 /* 2948 * Count number of packages that would be skipped due to the 2949 * specified package having failed. 2950 * 2951 * Call with mode 1 to count, and mode 0 to clear the 2952 * cumulative rscan flag (used to de-duplicate the count). 2953 * 2954 * Must be serialized. 2955 */ 2956 static int 2957 buildskipcount_dueto(pkg_t *pkg, int mode) 2958 { 2959 pkglink_t *link; 2960 pkg_t *scan; 2961 int total; 2962 2963 total = 0; 2964 PKGLIST_FOREACH(link, &pkg->deponi_list) { 2965 scan = link->pkg; 2966 if (scan == NULL || scan->rscan == mode) 2967 continue; 2968 scan->rscan = mode; 2969 ++total; 2970 total += buildskipcount_dueto(scan, mode); 2971 } 2972 return total; 2973 } 2974 2975 /* 2976 * The master ptyfd is in non-blocking mode. Drain up to 1024 bytes 2977 * and update wmsg->lines and *wdog_timep as appropriate. 2978 * 2979 * This function will poll, stalling up to 1 second. 2980 */ 2981 static int 2982 mptylogpoll(int ptyfd, int fdlog, wmsg_t *wmsg, time_t *wdog_timep) 2983 { 2984 struct pollfd pfd; 2985 char buf[1024]; 2986 ssize_t r; 2987 2988 pfd.fd = ptyfd; 2989 pfd.events = POLLIN; 2990 pfd.revents = 0; 2991 2992 poll(&pfd, 1, 1000); 2993 if (pfd.revents) { 2994 r = read(ptyfd, buf, sizeof(buf)); 2995 if (r > 0) { 2996 *wdog_timep = time(NULL); 2997 if (r > 0 && fdlog >= 0) 2998 write(fdlog, buf, r); 2999 while (--r >= 0) { 3000 if (buf[r] == '\n') 3001 ++wmsg->lines; 3002 } 3003 return MPTY_DATA; 3004 } else if (r < 0) { 3005 if (errno != EINTR && errno != EAGAIN) 3006 return MPTY_FAILED; 3007 return MPTY_AGAIN; 3008 } else if (r == 0) { 3009 return MPTY_EOF; 3010 } 3011 } 3012 return MPTY_AGAIN; 3013 } 3014 3015 /* 3016 * Copy a (package) file from (src) to (dst), use an intermediate file and 3017 * rename to ensure that interruption does not leave us with a corrupt 3018 * package file. 3019 * 3020 * This is called by the WORKER process. 3021 * 3022 * (dsynth management thread -> WORKER process -> sub-processes) 3023 */ 3024 #define COPYBLKSIZE 32768 3025 3026 int 3027 copyfile(char *src, char *dst) 3028 { 3029 char *tmp; 3030 char *buf; 3031 int fd1; 3032 int fd2; 3033 int error = 0; 3034 int mask; 3035 ssize_t r; 3036 3037 asprintf(&tmp, "%s.new", dst); 3038 buf = malloc(COPYBLKSIZE); 3039 3040 mask = sigsetmask(sigmask(SIGTERM)|sigmask(SIGINT)|sigmask(SIGHUP)); 3041 fd1 = open(src, O_RDONLY|O_CLOEXEC); 3042 fd2 = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0644); 3043 CopyFileFd = fd1; 3044 sigsetmask(mask); 3045 while ((r = read(fd1, buf, COPYBLKSIZE)) > 0) { 3046 if (write(fd2, buf, r) != r) 3047 error = 1; 3048 } 3049 if (r < 0) 3050 error = 1; 3051 mask = sigsetmask(sigmask(SIGTERM)|sigmask(SIGINT)|sigmask(SIGHUP)); 3052 CopyFileFd = -1; 3053 close(fd1); 3054 close(fd2); 3055 sigsetmask(mask); 3056 if (error) { 3057 remove(tmp); 3058 } else { 3059 if (rename(tmp, dst)) { 3060 error = 1; 3061 remove(tmp); 3062 } 3063 } 3064 3065 freestrp(&buf); 3066 freestrp(&tmp); 3067 3068 return error; 3069 } 3070 3071 /* 3072 * doHook() 3073 * 3074 * primary process (threaded) - run_start, run_end, pkg_ignored, pkg_skipped 3075 * worker process (threaded) - pkg_sucess, pkg_failure 3076 * 3077 * If waitfor is non-zero this hook will be serialized. 3078 */ 3079 static void 3080 doHook(pkg_t *pkg, const char *id, const char *path, int waitfor) 3081 { 3082 if (path == NULL) 3083 return; 3084 while (waitfor && getbulk() != NULL) 3085 ; 3086 if (pkg) 3087 queuebulk(pkg->portdir, id, path, pkg->pkgfile); 3088 else 3089 queuebulk(NULL, id, path, NULL); 3090 while (waitfor && getbulk() != NULL) 3091 ; 3092 } 3093 3094 /* 3095 * Execute hook (backend) 3096 * 3097 * s1 - portdir 3098 * s2 - id 3099 * s3 - script path 3100 * s4 - pkgfile (if applicable) 3101 */ 3102 static void 3103 childHookRun(bulk_t *bulk) 3104 { 3105 const char *cav[MAXCAC]; 3106 buildenv_t benv[MAXCAC]; 3107 char buf1[128]; 3108 char buf2[128]; 3109 char buf3[128]; 3110 char buf4[128]; 3111 FILE *fp; 3112 char *ptr; 3113 size_t len; 3114 pid_t pid; 3115 int cac; 3116 int bi; 3117 3118 cac = 0; 3119 bi = 0; 3120 bzero(benv, sizeof(benv)); 3121 3122 cav[cac++] = bulk->s3; 3123 3124 benv[bi].label = "PROFILE"; 3125 benv[bi].data = Profile; 3126 ++bi; 3127 3128 benv[bi].label = "DIR_PACKAGES"; 3129 benv[bi].data = PackagesPath; 3130 ++bi; 3131 3132 benv[bi].label = "DIR_REPOSITORY"; 3133 benv[bi].data = RepositoryPath; 3134 ++bi; 3135 3136 benv[bi].label = "DIR_PORTS"; 3137 benv[bi].data = DPortsPath; 3138 ++bi; 3139 3140 benv[bi].label = "DIR_OPTIONS"; 3141 benv[bi].data = OptionsPath; 3142 ++bi; 3143 3144 benv[bi].label = "DIR_DISTFILES"; 3145 benv[bi].data = DistFilesPath; 3146 ++bi; 3147 3148 benv[bi].label = "DIR_LOGS"; 3149 benv[bi].data = LogsPath; 3150 ++bi; 3151 3152 benv[bi].label = "DIR_BUILDBASE"; 3153 benv[bi].data = BuildBase; 3154 ++bi; 3155 3156 if (strcmp(bulk->s2, "hook_run_start") == 0) { 3157 snprintf(buf1, sizeof(buf1), "%d", BuildTotal); 3158 benv[bi].label = "PORTS_QUEUED"; 3159 benv[bi].data = buf1; 3160 ++bi; 3161 } else if (strcmp(bulk->s2, "hook_run_end") == 0) { 3162 snprintf(buf1, sizeof(buf1), "%d", BuildSuccessCount); 3163 benv[bi].label = "PORTS_BUILT"; 3164 benv[bi].data = buf1; 3165 ++bi; 3166 snprintf(buf2, sizeof(buf2), "%d", BuildFailCount); 3167 benv[bi].label = "PORTS_FAILED"; 3168 benv[bi].data = buf2; 3169 ++bi; 3170 snprintf(buf3, sizeof(buf3), "%d", BuildIgnoreCount); 3171 benv[bi].label = "PORTS_IGNORED"; 3172 benv[bi].data = buf3; 3173 ++bi; 3174 snprintf(buf4, sizeof(buf4), "%d", BuildSkipCount); 3175 benv[bi].label = "PORTS_SKIPPED"; 3176 benv[bi].data = buf4; 3177 ++bi; 3178 } else { 3179 /* 3180 * success, failure, ignored, skipped 3181 */ 3182 benv[bi].label = "RESULT"; 3183 if (strcmp(bulk->s2, "hook_pkg_success") == 0) { 3184 benv[bi].data = "success"; 3185 } else if (strcmp(bulk->s2, "hook_pkg_failure") == 0) { 3186 benv[bi].data = "failure"; 3187 } else if (strcmp(bulk->s2, "hook_pkg_ignored") == 0) { 3188 benv[bi].data = "ignored"; 3189 } else if (strcmp(bulk->s2, "hook_pkg_skipped") == 0) { 3190 benv[bi].data = "skipped"; 3191 } else { 3192 dfatal("Unknown hook id: %s", bulk->s2); 3193 /* NOT REACHED */ 3194 } 3195 ++bi; 3196 3197 /* 3198 * For compatibility with synth: 3199 * 3200 * ORIGIN does not include any @flavor, thus it is suitable 3201 * for finding the actual port directory/subdirectory. 3202 * 3203 * FLAVOR is set to ORIGIN if there is no flavor, otherwise 3204 * it is set to only the flavor sans the '@'. 3205 */ 3206 if ((ptr = strchr(bulk->s1, '@')) != NULL) { 3207 snprintf(buf1, sizeof(buf1), "%*.*s", 3208 (int)(ptr - bulk->s1), 3209 (int)(ptr - bulk->s1), 3210 bulk->s1); 3211 benv[bi].label = "ORIGIN"; 3212 benv[bi].data = buf1; 3213 ++bi; 3214 benv[bi].label = "FLAVOR"; 3215 benv[bi].data = ptr + 1; 3216 ++bi; 3217 } else { 3218 benv[bi].label = "ORIGIN"; 3219 benv[bi].data = bulk->s1; 3220 ++bi; 3221 benv[bi].label = "FLAVOR"; 3222 benv[bi].data = bulk->s1; 3223 ++bi; 3224 } 3225 benv[bi].label = "PKGNAME"; 3226 benv[bi].data = bulk->s4; 3227 ++bi; 3228 } 3229 3230 benv[bi].label = NULL; 3231 benv[bi].data = NULL; 3232 3233 fp = dexec_open(bulk->s1, cav, cac, &pid, benv, 0, 0); 3234 while ((ptr = fgetln(fp, &len)) != NULL) 3235 ; 3236 3237 if (dexec_close(fp, pid)) { 3238 dlog(DLOG_ALL, 3239 "[XXX] %s SCRIPT %s (%s)\n", 3240 bulk->s1, bulk->s2, bulk->s3); 3241 } 3242 } 3243 3244 /* 3245 * Adjusts dload[0] by adding in t_pw (processes waiting on page-fault). 3246 * We don't want load reductions due to e.g. thrashing to cause dsynth 3247 * to increase the dynamic limit because it thinks the load is low. 3248 * 3249 * This has a desirable property. If the system pager cannot keep up 3250 * with process demand t_pw will spike while loadavg will only drop 3251 * slowly, resulting in a high adjusted load calculation that causes 3252 * dsynth to quickly clamp-down the limit. If the condition alleviates, 3253 * the limit will then rise slowly again, possibly even before existing 3254 * jobs are retired to meet the clamp-down from the original spike. 3255 */ 3256 static void 3257 adjloadavg(double *dload) 3258 { 3259 #if defined(__DragonFly__) 3260 struct vmtotal total; 3261 size_t size; 3262 3263 size = sizeof(total); 3264 if (sysctlbyname("vm.vmtotal", &total, &size, NULL, 0) == 0) { 3265 dload[0] += (double)total.t_pw; 3266 } 3267 #else 3268 dload[0] += 0.0; /* just avoid compiler 'unused' warnings */ 3269 #endif 3270 } 3271 3272 /* 3273 * The list of pkgs has already been flagged PKGF_PACKAGED if a pkg 3274 * file exists. Check if the ports directory contents for such packages 3275 * has changed by comparing against a small DBM database that we maintain. 3276 * 3277 * Force-clear PKGF_PACKAGED if the ports directory content has changed. 3278 * 3279 * If no DBM database entry is present, update the entry and assume that 3280 * the package does not need to be rebuilt (allows the .dbm file to be 3281 * manually deleted without forcing a complete rebuild). 3282 */ 3283 static 3284 void 3285 check_packaged(const char *dbmpath, pkg_t *pkgs) 3286 { 3287 pkg_t *scan; 3288 datum key; 3289 datum data; 3290 char *buf; 3291 3292 if (CheckDBM == NULL) { 3293 dlog(DLOG_ABN, "[XXX] Unable to open/create dbm %s\n", dbmpath); 3294 return; 3295 } 3296 for (scan = pkgs; scan; scan = scan->bnext) { 3297 if ((scan->flags & PKGF_PACKAGED) == 0) 3298 continue; 3299 key.dptr = scan->portdir; 3300 key.dsize = strlen(scan->portdir); 3301 data = dbm_fetch(CheckDBM, key); 3302 if (data.dptr && data.dsize == sizeof(uint32_t) && 3303 *(uint32_t *)data.dptr != scan->crc32) { 3304 scan->flags &= ~PKGF_PACKAGED; 3305 asprintf(&buf, "%s/%s", RepositoryPath, scan->pkgfile); 3306 if (OverridePkgDeleteOpt >= 2) { 3307 scan->flags |= PKGF_PACKAGED; 3308 dlog(DLOG_ALL, 3309 "[XXX] %s DELETE-PACKAGE %s " 3310 "(port content changed CRC %08x/%08x " 3311 "OVERRIDE, NOT DELETED)\n", 3312 scan->portdir, buf, 3313 *(uint32_t *)data.dptr, scan->crc32); 3314 } else if (remove(buf) < 0) { 3315 dlog(DLOG_ALL, 3316 "[XXX] %s DELETE-PACKAGE %s (failed)\n", 3317 scan->portdir, buf); 3318 } else { 3319 dlog(DLOG_ALL, 3320 "[XXX] %s DELETE-PACKAGE %s " 3321 "(port content changed CRC %08x/%08x)\n", 3322 scan->portdir, buf, 3323 *(uint32_t *)data.dptr, scan->crc32); 3324 } 3325 freestrp(&buf); 3326 } else if (data.dptr == NULL) { 3327 data.dptr = &scan->crc32; 3328 data.dsize = sizeof(scan->crc32); 3329 dbm_store(CheckDBM, key, data, DBM_REPLACE); 3330 } 3331 } 3332 } 3333