build.cc 118 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632
  1. #include "config.h"
  2. #include "references.hh"
  3. #include "pathlocks.hh"
  4. #include "misc.hh"
  5. #include "globals.hh"
  6. #include "local-store.hh"
  7. #include "util.hh"
  8. #include "archive.hh"
  9. #include "affinity.hh"
  10. #include "builtins.hh"
  11. #include <map>
  12. #include <sstream>
  13. #include <algorithm>
  14. #include <limits.h>
  15. #include <time.h>
  16. #include <sys/time.h>
  17. #include <sys/wait.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <sys/utsname.h>
  21. #include <fcntl.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <cstring>
  26. #include <stdint.h>
  27. #include <pwd.h>
  28. #include <grp.h>
  29. #include <zlib.h>
  30. #if HAVE_BZLIB_H
  31. # include <bzlib.h>
  32. #endif
  33. /* Includes required for chroot support. */
  34. #if HAVE_SYS_PARAM_H
  35. #include <sys/param.h>
  36. #endif
  37. #if HAVE_SYS_MOUNT_H
  38. #include <sys/mount.h>
  39. #endif
  40. #if HAVE_SYS_SYSCALL_H
  41. #include <sys/syscall.h>
  42. #endif
  43. #if HAVE_SCHED_H
  44. #include <sched.h>
  45. #endif
  46. #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE)
  47. #define CLONE_ENABLED defined(CLONE_NEWNS)
  48. #if defined(SYS_pivot_root)
  49. #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root,put_old))
  50. #endif
  51. #if CHROOT_ENABLED
  52. #include <sys/socket.h>
  53. #include <sys/ioctl.h>
  54. #include <net/if.h>
  55. #include <netinet/ip.h>
  56. #endif
  57. #if __linux__
  58. #include <sys/personality.h>
  59. #endif
  60. #if HAVE_STATVFS
  61. #include <sys/statvfs.h>
  62. #endif
  63. namespace nix {
  64. using std::map;
  65. /* Forward definition. */
  66. class Worker;
  67. /* A pointer to a goal. */
  68. class Goal;
  69. class DerivationGoal;
  70. typedef std::shared_ptr<Goal> GoalPtr;
  71. typedef std::weak_ptr<Goal> WeakGoalPtr;
  72. struct CompareGoalPtrs {
  73. bool operator() (const GoalPtr & a, const GoalPtr & b);
  74. };
  75. /* Set of goals. */
  76. typedef set<GoalPtr, CompareGoalPtrs> Goals;
  77. typedef list<WeakGoalPtr> WeakGoals;
  78. /* A map of paths to goals (and the other way around). */
  79. typedef map<Path, WeakGoalPtr> WeakGoalMap;
  80. class Goal : public std::enable_shared_from_this<Goal>
  81. {
  82. public:
  83. typedef enum {ecBusy, ecSuccess, ecFailed, ecNoSubstituters, ecIncompleteClosure} ExitCode;
  84. protected:
  85. /* Backlink to the worker. */
  86. Worker & worker;
  87. /* Goals that this goal is waiting for. */
  88. Goals waitees;
  89. /* Goals waiting for this one to finish. Must use weak pointers
  90. here to prevent cycles. */
  91. WeakGoals waiters;
  92. /* Number of goals we are/were waiting for that have failed. */
  93. unsigned int nrFailed;
  94. /* Number of substitution goals we are/were waiting for that
  95. failed because there are no substituters. */
  96. unsigned int nrNoSubstituters;
  97. /* Number of substitution goals we are/were waiting for that
  98. failed because othey had unsubstitutable references. */
  99. unsigned int nrIncompleteClosure;
  100. /* Name of this goal for debugging purposes. */
  101. string name;
  102. /* Whether the goal is finished. */
  103. ExitCode exitCode;
  104. Goal(Worker & worker) : worker(worker)
  105. {
  106. nrFailed = nrNoSubstituters = nrIncompleteClosure = 0;
  107. exitCode = ecBusy;
  108. }
  109. virtual ~Goal()
  110. {
  111. trace("goal destroyed");
  112. }
  113. public:
  114. virtual void work() = 0;
  115. void addWaitee(GoalPtr waitee);
  116. virtual void waiteeDone(GoalPtr waitee, ExitCode result);
  117. virtual void handleChildOutput(int fd, const string & data)
  118. {
  119. abort();
  120. }
  121. virtual void handleEOF(int fd)
  122. {
  123. abort();
  124. }
  125. void trace(const format & f);
  126. string getName()
  127. {
  128. return name;
  129. }
  130. ExitCode getExitCode()
  131. {
  132. return exitCode;
  133. }
  134. /* Callback in case of a timeout. It should wake up its waiters,
  135. get rid of any running child processes that are being monitored
  136. by the worker (important!), etc. */
  137. virtual void timedOut() = 0;
  138. virtual string key() = 0;
  139. protected:
  140. void amDone(ExitCode result);
  141. };
  142. bool CompareGoalPtrs::operator() (const GoalPtr & a, const GoalPtr & b) {
  143. string s1 = a->key();
  144. string s2 = b->key();
  145. return s1 < s2;
  146. }
  147. /* A mapping used to remember for each child process to what goal it
  148. belongs, and file descriptors for receiving log data and output
  149. path creation commands. */
  150. struct Child
  151. {
  152. WeakGoalPtr goal;
  153. set<int> fds;
  154. bool respectTimeouts;
  155. bool inBuildSlot;
  156. time_t lastOutput; /* time we last got output on stdout/stderr */
  157. time_t timeStarted;
  158. };
  159. typedef map<pid_t, Child> Children;
  160. /* The worker class. */
  161. class Worker
  162. {
  163. private:
  164. /* Note: the worker should only have strong pointers to the
  165. top-level goals. */
  166. /* The top-level goals of the worker. */
  167. Goals topGoals;
  168. /* Goals that are ready to do some work. */
  169. WeakGoals awake;
  170. /* Goals waiting for a build slot. */
  171. WeakGoals wantingToBuild;
  172. /* Child processes currently running. */
  173. Children children;
  174. /* Number of build slots occupied. This includes local builds and
  175. substitutions but not remote builds via the build hook. */
  176. unsigned int nrLocalBuilds;
  177. /* Maps used to prevent multiple instantiations of a goal for the
  178. same derivation / path. */
  179. WeakGoalMap derivationGoals;
  180. WeakGoalMap substitutionGoals;
  181. /* Goals waiting for busy paths to be unlocked. */
  182. WeakGoals waitingForAnyGoal;
  183. /* Goals sleeping for a few seconds (polling a lock). */
  184. WeakGoals waitingForAWhile;
  185. /* Last time the goals in `waitingForAWhile' where woken up. */
  186. time_t lastWokenUp;
  187. public:
  188. /* Set if at least one derivation had a BuildError (i.e. permanent
  189. failure). */
  190. bool permanentFailure;
  191. /* Set if at least one derivation had a timeout. */
  192. bool timedOut;
  193. LocalStore & store;
  194. std::shared_ptr<Agent> hook;
  195. std::shared_ptr<Agent> substituter;
  196. Worker(LocalStore & store);
  197. ~Worker();
  198. /* Make a goal (with caching). */
  199. GoalPtr makeDerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, BuildMode buildMode = bmNormal);
  200. GoalPtr makeSubstitutionGoal(const Path & storePath, bool repair = false);
  201. /* Remove a dead goal. */
  202. void removeGoal(GoalPtr goal);
  203. /* Wake up a goal (i.e., there is something for it to do). */
  204. void wakeUp(GoalPtr goal);
  205. /* Return the number of local build and substitution processes
  206. currently running (but not remote builds via the build
  207. hook). */
  208. unsigned int getNrLocalBuilds();
  209. /* Registers a running child process. `inBuildSlot' means that
  210. the process counts towards the jobs limit. */
  211. void childStarted(GoalPtr goal, pid_t pid,
  212. const set<int> & fds, bool inBuildSlot, bool respectTimeouts);
  213. /* Unregisters a running child process. `wakeSleepers' should be
  214. false if there is no sense in waking up goals that are sleeping
  215. because they can't run yet (e.g., there is no free build slot,
  216. or the hook would still say `postpone'). */
  217. void childTerminated(pid_t pid, bool wakeSleepers = true);
  218. /* Put `goal' to sleep until a build slot becomes available (which
  219. might be right away). */
  220. void waitForBuildSlot(GoalPtr goal);
  221. /* Wait for any goal to finish. Pretty indiscriminate way to
  222. wait for some resource that some other goal is holding. */
  223. void waitForAnyGoal(GoalPtr goal);
  224. /* Wait for a few seconds and then retry this goal. Used when
  225. waiting for a lock held by another process. This kind of
  226. polling is inefficient, but POSIX doesn't really provide a way
  227. to wait for multiple locks in the main select() loop. */
  228. void waitForAWhile(GoalPtr goal);
  229. /* Loop until the specified top-level goals have finished. */
  230. void run(const Goals & topGoals);
  231. /* Wait for input to become available. */
  232. void waitForInput();
  233. unsigned int exitStatus();
  234. };
  235. //////////////////////////////////////////////////////////////////////
  236. void addToWeakGoals(WeakGoals & goals, GoalPtr p)
  237. {
  238. // FIXME: necessary?
  239. // FIXME: O(n)
  240. foreach (WeakGoals::iterator, i, goals)
  241. if (i->lock() == p) return;
  242. goals.push_back(p);
  243. }
  244. void Goal::addWaitee(GoalPtr waitee)
  245. {
  246. waitees.insert(waitee);
  247. addToWeakGoals(waitee->waiters, shared_from_this());
  248. }
  249. void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
  250. {
  251. assert(waitees.find(waitee) != waitees.end());
  252. waitees.erase(waitee);
  253. trace(format("waitee `%1%' done; %2% left") %
  254. waitee->name % waitees.size());
  255. if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed;
  256. if (result == ecNoSubstituters) ++nrNoSubstituters;
  257. if (result == ecIncompleteClosure) ++nrIncompleteClosure;
  258. if (waitees.empty() || (result == ecFailed && !settings.keepGoing)) {
  259. /* If we failed and keepGoing is not set, we remove all
  260. remaining waitees. */
  261. foreach (Goals::iterator, i, waitees) {
  262. GoalPtr goal = *i;
  263. WeakGoals waiters2;
  264. foreach (WeakGoals::iterator, j, goal->waiters)
  265. if (j->lock() != shared_from_this()) waiters2.push_back(*j);
  266. goal->waiters = waiters2;
  267. }
  268. waitees.clear();
  269. worker.wakeUp(shared_from_this());
  270. }
  271. }
  272. void Goal::amDone(ExitCode result)
  273. {
  274. trace("done");
  275. assert(exitCode == ecBusy);
  276. assert(result == ecSuccess || result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure);
  277. exitCode = result;
  278. foreach (WeakGoals::iterator, i, waiters) {
  279. GoalPtr goal = i->lock();
  280. if (goal) goal->waiteeDone(shared_from_this(), result);
  281. }
  282. waiters.clear();
  283. worker.removeGoal(shared_from_this());
  284. }
  285. void Goal::trace(const format & f)
  286. {
  287. debug(format("%1%: %2%") % name % f);
  288. }
  289. //////////////////////////////////////////////////////////////////////
  290. /* Restore default handling of SIGPIPE, otherwise some programs will
  291. randomly say "Broken pipe". */
  292. static void restoreSIGPIPE()
  293. {
  294. struct sigaction act, oact;
  295. act.sa_handler = SIG_DFL;
  296. act.sa_flags = 0;
  297. sigemptyset(&act.sa_mask);
  298. if (sigaction(SIGPIPE, &act, &oact)) throw SysError("resetting SIGPIPE");
  299. }
  300. //////////////////////////////////////////////////////////////////////
  301. class UserLock
  302. {
  303. private:
  304. /* POSIX locks suck. If we have a lock on a file, and we open and
  305. close that file again (without closing the original file
  306. descriptor), we lose the lock. So we have to be *very* careful
  307. not to open a lock file on which we are holding a lock. */
  308. static PathSet lockedPaths; /* !!! not thread-safe */
  309. Path fnUserLock;
  310. AutoCloseFD fdUserLock;
  311. string user;
  312. uid_t uid;
  313. gid_t gid;
  314. std::vector<gid_t> supplementaryGIDs;
  315. public:
  316. UserLock();
  317. ~UserLock();
  318. void acquire();
  319. void release();
  320. void kill();
  321. string getUser() { return user; }
  322. uid_t getUID() { return uid; }
  323. uid_t getGID() { return gid; }
  324. std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
  325. bool enabled() { return uid != 0; }
  326. };
  327. PathSet UserLock::lockedPaths;
  328. UserLock::UserLock()
  329. {
  330. uid = gid = 0;
  331. }
  332. UserLock::~UserLock()
  333. {
  334. release();
  335. }
  336. void UserLock::acquire()
  337. {
  338. assert(uid == 0);
  339. assert(settings.buildUsersGroup != "");
  340. /* Get the members of the build-users-group. */
  341. struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
  342. if (!gr)
  343. throw Error(format("the group `%1%' specified in `build-users-group' does not exist")
  344. % settings.buildUsersGroup);
  345. gid = gr->gr_gid;
  346. /* Copy the result of getgrnam. */
  347. Strings users;
  348. for (char * * p = gr->gr_mem; *p; ++p) {
  349. debug(format("found build user `%1%'") % *p);
  350. users.push_back(*p);
  351. }
  352. if (users.empty())
  353. throw Error(format("the build users group `%1%' has no members")
  354. % settings.buildUsersGroup);
  355. /* Find a user account that isn't currently in use for another
  356. build. */
  357. foreach (Strings::iterator, i, users) {
  358. debug(format("trying user `%1%'") % *i);
  359. struct passwd * pw = getpwnam(i->c_str());
  360. if (!pw)
  361. throw Error(format("the user `%1%' in the group `%2%' does not exist")
  362. % *i % settings.buildUsersGroup);
  363. createDirs(settings.nixStateDir + "/userpool");
  364. fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
  365. if (lockedPaths.find(fnUserLock) != lockedPaths.end())
  366. /* We already have a lock on this one. */
  367. continue;
  368. AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT, 0600);
  369. if (fd == -1)
  370. throw SysError(format("opening user lock `%1%'") % fnUserLock);
  371. closeOnExec(fd);
  372. if (lockFile(fd, ltWrite, false)) {
  373. fdUserLock = fd.borrow();
  374. lockedPaths.insert(fnUserLock);
  375. user = *i;
  376. uid = pw->pw_uid;
  377. /* Sanity check... */
  378. if (uid == getuid() || uid == geteuid())
  379. throw Error(format("the build user should not be a member of `%1%'")
  380. % settings.buildUsersGroup);
  381. /* Get the list of supplementary groups of this build user. This
  382. is usually either empty or contains a group such as "kvm". */
  383. supplementaryGIDs.resize(10);
  384. int ngroups = supplementaryGIDs.size();
  385. int err = getgrouplist(pw->pw_name, pw->pw_gid,
  386. supplementaryGIDs.data(), &ngroups);
  387. if (err == -1)
  388. throw Error(format("failed to get list of supplementary groups for ‘%1%’") % pw->pw_name);
  389. supplementaryGIDs.resize(ngroups);
  390. return;
  391. }
  392. }
  393. throw Error(format("all build users are currently in use; "
  394. "consider creating additional users and adding them to the `%1%' group")
  395. % settings.buildUsersGroup);
  396. }
  397. void UserLock::release()
  398. {
  399. if (uid == 0) return;
  400. fdUserLock.close(); /* releases lock */
  401. assert(lockedPaths.find(fnUserLock) != lockedPaths.end());
  402. lockedPaths.erase(fnUserLock);
  403. fnUserLock = "";
  404. uid = 0;
  405. }
  406. void UserLock::kill()
  407. {
  408. assert(enabled());
  409. killUser(uid);
  410. }
  411. //////////////////////////////////////////////////////////////////////
  412. typedef map<string, string> HashRewrites;
  413. string rewriteHashes(string s, const HashRewrites & rewrites)
  414. {
  415. foreach (HashRewrites::const_iterator, i, rewrites) {
  416. assert(i->first.size() == i->second.size());
  417. size_t j = 0;
  418. while ((j = s.find(i->first, j)) != string::npos) {
  419. debug(format("rewriting @ %1%") % j);
  420. s.replace(j, i->second.size(), i->second);
  421. }
  422. }
  423. return s;
  424. }
  425. //////////////////////////////////////////////////////////////////////
  426. typedef enum {rpAccept, rpDecline, rpPostpone} HookReply;
  427. class SubstitutionGoal;
  428. class DerivationGoal : public Goal
  429. {
  430. private:
  431. /* The path of the derivation. */
  432. Path drvPath;
  433. /* The specific outputs that we need to build. Empty means all of
  434. them. */
  435. StringSet wantedOutputs;
  436. /* Whether additional wanted outputs have been added. */
  437. bool needRestart;
  438. /* Whether to retry substituting the outputs after building the
  439. inputs. */
  440. bool retrySubstitution;
  441. /* The derivation stored at drvPath. */
  442. Derivation drv;
  443. /* The remainder is state held during the build. */
  444. /* Locks on the output paths. */
  445. PathLocks outputLocks;
  446. /* All input paths (that is, the union of FS closures of the
  447. immediate input paths). */
  448. PathSet inputPaths;
  449. /* Referenceable paths (i.e., input and output paths). */
  450. PathSet allPaths;
  451. /* Outputs that are already valid. If we're repairing, these are
  452. the outputs that are valid *and* not corrupt. */
  453. PathSet validPaths;
  454. /* Outputs that are corrupt or not valid. */
  455. PathSet missingPaths;
  456. /* User selected for running the builder. */
  457. UserLock buildUser;
  458. /* The process ID of the builder. */
  459. Pid pid;
  460. /* The temporary directory. */
  461. Path tmpDir;
  462. /* The path of the temporary directory in the sandbox. */
  463. Path tmpDirInSandbox;
  464. /* File descriptor for the log file. */
  465. FILE * fLogFile;
  466. gzFile gzLogFile;
  467. #if HAVE_BZLIB_H
  468. BZFILE * bzLogFile;
  469. #endif
  470. AutoCloseFD fdLogFile;
  471. /* Number of bytes received from the builder's stdout/stderr. */
  472. unsigned long logSize;
  473. /* Pipe for the builder's standard output/error. */
  474. Pipe builderOut;
  475. /* The build hook. */
  476. std::shared_ptr<Agent> hook;
  477. /* Whether we're currently doing a chroot build. */
  478. bool useChroot;
  479. Path chrootRootDir;
  480. /* RAII object to delete the chroot directory. */
  481. std::shared_ptr<AutoDelete> autoDelChroot;
  482. /* All inputs that are regular files. */
  483. PathSet regularInputPaths;
  484. /* Whether this is a fixed-output derivation. */
  485. bool fixedOutput;
  486. typedef void (DerivationGoal::*GoalState)();
  487. GoalState state;
  488. /* Stuff we need to pass to runChild(). */
  489. typedef map<Path, Path> DirsInChroot; // maps target path to source path
  490. DirsInChroot dirsInChroot;
  491. typedef map<string, string> Environment;
  492. Environment env;
  493. /* Hash rewriting. */
  494. HashRewrites rewritesToTmp, rewritesFromTmp;
  495. typedef map<Path, Path> RedirectedOutputs;
  496. RedirectedOutputs redirectedOutputs;
  497. BuildMode buildMode;
  498. /* If we're repairing without a chroot, there may be outputs that
  499. are valid but corrupt. So we redirect these outputs to
  500. temporary paths. */
  501. PathSet redirectedBadOutputs;
  502. /* The current round, if we're building multiple times. */
  503. unsigned int curRound = 1;
  504. unsigned int nrRounds;
  505. /* Path registration info from the previous round, if we're
  506. building multiple times. Since this contains the hash, it
  507. allows us to compare whether two rounds produced the same
  508. result. */
  509. ValidPathInfos prevInfos;
  510. BuildResult result;
  511. public:
  512. DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode = bmNormal);
  513. ~DerivationGoal();
  514. void timedOut() override;
  515. string key()
  516. {
  517. /* Ensure that derivations get built in order of their name,
  518. i.e. a derivation named "aardvark" always comes before
  519. "baboon". And substitution goals always happen before
  520. derivation goals (due to "b$"). */
  521. return "b$" + storePathToName(drvPath) + "$" + drvPath;
  522. }
  523. void work();
  524. Path getDrvPath()
  525. {
  526. return drvPath;
  527. }
  528. /* Add wanted outputs to an already existing derivation goal. */
  529. void addWantedOutputs(const StringSet & outputs);
  530. BuildResult getResult() { return result; }
  531. private:
  532. /* The states. */
  533. void init();
  534. void haveDerivation();
  535. void outputsSubstituted();
  536. void closureRepaired();
  537. void inputsRealised();
  538. void tryToBuild();
  539. void buildDone();
  540. /* Is the build hook willing to perform the build? */
  541. HookReply tryBuildHook();
  542. /* Start building a derivation. */
  543. void startBuilder();
  544. /* Run the builder's process. */
  545. void runChild();
  546. friend int childEntry(void *);
  547. /* Check that the derivation outputs all exist and register them
  548. as valid. */
  549. void registerOutputs();
  550. /* Open a log file and a pipe to it. */
  551. Path openLogFile();
  552. /* Close the log file. */
  553. void closeLogFile();
  554. /* Delete the temporary directory, if we have one. */
  555. void deleteTmpDir(bool force);
  556. /* Callback used by the worker to write to the log. */
  557. void handleChildOutput(int fd, const string & data);
  558. void handleEOF(int fd);
  559. /* Return the set of (in)valid paths. */
  560. PathSet checkPathValidity(bool returnValid, bool checkHash);
  561. /* Abort the goal if `path' failed to build. */
  562. bool pathFailed(const Path & path);
  563. /* Forcibly kill the child process, if any. */
  564. void killChild();
  565. Path addHashRewrite(const Path & path);
  566. void repairClosure();
  567. void done(BuildResult::Status status, const string & msg = "");
  568. };
  569. DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs, Worker & worker, BuildMode buildMode)
  570. : Goal(worker)
  571. , wantedOutputs(wantedOutputs)
  572. , needRestart(false)
  573. , retrySubstitution(false)
  574. , fLogFile(0)
  575. , gzLogFile(0)
  576. #if HAVE_BZLIB_H
  577. , bzLogFile(0)
  578. #endif
  579. , useChroot(false)
  580. , buildMode(buildMode)
  581. {
  582. this->drvPath = drvPath;
  583. state = &DerivationGoal::init;
  584. name = (format("building of `%1%'") % drvPath).str();
  585. trace("created");
  586. /* Prevent the .chroot directory from being
  587. garbage-collected. (See isActiveTempFile() in gc.cc.) */
  588. worker.store.addTempRoot(drvPath);
  589. }
  590. DerivationGoal::~DerivationGoal()
  591. {
  592. /* Careful: we should never ever throw an exception from a
  593. destructor. */
  594. try { killChild(); } catch (...) { ignoreException(); }
  595. try { deleteTmpDir(false); } catch (...) { ignoreException(); }
  596. try { closeLogFile(); } catch (...) { ignoreException(); }
  597. }
  598. void DerivationGoal::killChild()
  599. {
  600. if (pid != -1) {
  601. worker.childTerminated(pid);
  602. if (buildUser.enabled()) {
  603. /* If we're using a build user, then there is a tricky
  604. race condition: if we kill the build user before the
  605. child has done its setuid() to the build user uid, then
  606. it won't be killed, and we'll potentially lock up in
  607. pid.wait(). So also send a conventional kill to the
  608. child. */
  609. ::kill(-pid, SIGKILL); /* ignore the result */
  610. buildUser.kill();
  611. pid.wait(true);
  612. } else
  613. pid.kill();
  614. assert(pid == -1);
  615. }
  616. /* If there was a build hook involved, remove it from the worker's
  617. children. */
  618. if (hook && hook->pid != -1) {
  619. worker.childTerminated(hook->pid);
  620. }
  621. hook.reset();
  622. }
  623. void DerivationGoal::timedOut()
  624. {
  625. if (settings.printBuildTrace)
  626. printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath);
  627. killChild();
  628. done(BuildResult::TimedOut);
  629. }
  630. void DerivationGoal::work()
  631. {
  632. (this->*state)();
  633. }
  634. void DerivationGoal::addWantedOutputs(const StringSet & outputs)
  635. {
  636. /* If we already want all outputs, there is nothing to do. */
  637. if (wantedOutputs.empty()) return;
  638. if (outputs.empty()) {
  639. wantedOutputs.clear();
  640. needRestart = true;
  641. } else
  642. foreach (StringSet::const_iterator, i, outputs)
  643. if (wantedOutputs.find(*i) == wantedOutputs.end()) {
  644. wantedOutputs.insert(*i);
  645. needRestart = true;
  646. }
  647. }
  648. void DerivationGoal::init()
  649. {
  650. trace("init");
  651. if (settings.readOnlyMode)
  652. throw Error(format("cannot build derivation `%1%' - no write access to the store") % drvPath);
  653. /* The first thing to do is to make sure that the derivation
  654. exists. If it doesn't, it may be created through a
  655. substitute. */
  656. if (buildMode == bmNormal && worker.store.isValidPath(drvPath)) {
  657. haveDerivation();
  658. return;
  659. }
  660. addWaitee(worker.makeSubstitutionGoal(drvPath));
  661. state = &DerivationGoal::haveDerivation;
  662. }
  663. void DerivationGoal::haveDerivation()
  664. {
  665. trace("loading derivation");
  666. if (nrFailed != 0) {
  667. printMsg(lvlError, format("cannot build missing derivation ‘%1%’") % drvPath);
  668. done(BuildResult::MiscFailure);
  669. return;
  670. }
  671. /* `drvPath' should already be a root, but let's be on the safe
  672. side: if the user forgot to make it a root, we wouldn't want
  673. things being garbage collected while we're busy. */
  674. worker.store.addTempRoot(drvPath);
  675. assert(worker.store.isValidPath(drvPath));
  676. /* Get the derivation. */
  677. drv = derivationFromPath(worker.store, drvPath);
  678. foreach (DerivationOutputs::iterator, i, drv.outputs)
  679. worker.store.addTempRoot(i->second.path);
  680. /* Check what outputs paths are not already valid. */
  681. PathSet invalidOutputs = checkPathValidity(false, buildMode == bmRepair);
  682. /* If they are all valid, then we're done. */
  683. if (invalidOutputs.size() == 0 && buildMode == bmNormal) {
  684. done(BuildResult::AlreadyValid);
  685. return;
  686. }
  687. /* Check whether any output previously failed to build. If so,
  688. don't bother. */
  689. foreach (PathSet::iterator, i, invalidOutputs)
  690. if (pathFailed(*i)) return;
  691. /* We are first going to try to create the invalid output paths
  692. through substitutes. If that doesn't work, we'll build
  693. them. */
  694. if (settings.useSubstitutes && substitutesAllowed(drv))
  695. foreach (PathSet::iterator, i, invalidOutputs)
  696. addWaitee(worker.makeSubstitutionGoal(*i, buildMode == bmRepair));
  697. if (waitees.empty()) /* to prevent hang (no wake-up event) */
  698. outputsSubstituted();
  699. else
  700. state = &DerivationGoal::outputsSubstituted;
  701. }
  702. void DerivationGoal::outputsSubstituted()
  703. {
  704. trace("all outputs substituted (maybe)");
  705. if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback)
  706. throw Error(format("some substitutes for the outputs of derivation `%1%' failed (usually happens due to networking issues); try `--fallback' to build derivation from source ") % drvPath);
  707. /* If the substitutes form an incomplete closure, then we should
  708. build the dependencies of this derivation, but after that, we
  709. can still use the substitutes for this derivation itself. */
  710. if (nrIncompleteClosure > 0 && !retrySubstitution) retrySubstitution = true;
  711. nrFailed = nrNoSubstituters = nrIncompleteClosure = 0;
  712. if (needRestart) {
  713. needRestart = false;
  714. haveDerivation();
  715. return;
  716. }
  717. unsigned int nrInvalid = checkPathValidity(false, buildMode == bmRepair).size();
  718. if (buildMode == bmNormal && nrInvalid == 0) {
  719. done(BuildResult::Substituted);
  720. return;
  721. }
  722. if (buildMode == bmRepair && nrInvalid == 0) {
  723. repairClosure();
  724. return;
  725. }
  726. if (buildMode == bmCheck && nrInvalid > 0)
  727. throw Error(format("some outputs of `%1%' are not valid, so checking is not possible") % drvPath);
  728. /* Otherwise, at least one of the output paths could not be
  729. produced using a substitute. So we have to build instead. */
  730. /* Make sure checkPathValidity() from now on checks all
  731. outputs. */
  732. wantedOutputs = PathSet();
  733. /* The inputs must be built before we can build this goal. */
  734. foreach (DerivationInputs::iterator, i, drv.inputDrvs)
  735. addWaitee(worker.makeDerivationGoal(i->first, i->second, buildMode == bmRepair ? bmRepair : bmNormal));
  736. foreach (PathSet::iterator, i, drv.inputSrcs)
  737. addWaitee(worker.makeSubstitutionGoal(*i));
  738. if (waitees.empty()) /* to prevent hang (no wake-up event) */
  739. inputsRealised();
  740. else
  741. state = &DerivationGoal::inputsRealised;
  742. }
  743. void DerivationGoal::repairClosure()
  744. {
  745. /* If we're repairing, we now know that our own outputs are valid.
  746. Now check whether the other paths in the outputs closure are
  747. good. If not, then start derivation goals for the derivations
  748. that produced those outputs. */
  749. /* Get the output closure. */
  750. PathSet outputClosure;
  751. foreach (DerivationOutputs::iterator, i, drv.outputs) {
  752. if (!wantOutput(i->first, wantedOutputs)) continue;
  753. computeFSClosure(worker.store, i->second.path, outputClosure);
  754. }
  755. /* Filter out our own outputs (which we have already checked). */
  756. foreach (DerivationOutputs::iterator, i, drv.outputs)
  757. outputClosure.erase(i->second.path);
  758. /* Get all dependencies of this derivation so that we know which
  759. derivation is responsible for which path in the output
  760. closure. */
  761. PathSet inputClosure;
  762. computeFSClosure(worker.store, drvPath, inputClosure);
  763. std::map<Path, Path> outputsToDrv;
  764. foreach (PathSet::iterator, i, inputClosure)
  765. if (isDerivation(*i)) {
  766. Derivation drv = derivationFromPath(worker.store, *i);
  767. foreach (DerivationOutputs::iterator, j, drv.outputs)
  768. outputsToDrv[j->second.path] = *i;
  769. }
  770. /* Check each path (slow!). */
  771. PathSet broken;
  772. foreach (PathSet::iterator, i, outputClosure) {
  773. if (worker.store.pathContentsGood(*i)) continue;
  774. printMsg(lvlError, format("found corrupted or missing path `%1%' in the output closure of `%2%'") % *i % drvPath);
  775. Path drvPath2 = outputsToDrv[*i];
  776. if (drvPath2 == "")
  777. addWaitee(worker.makeSubstitutionGoal(*i, true));
  778. else
  779. addWaitee(worker.makeDerivationGoal(drvPath2, PathSet(), bmRepair));
  780. }
  781. if (waitees.empty()) {
  782. done(BuildResult::AlreadyValid);
  783. return;
  784. }
  785. state = &DerivationGoal::closureRepaired;
  786. }
  787. void DerivationGoal::closureRepaired()
  788. {
  789. trace("closure repaired");
  790. if (nrFailed > 0)
  791. throw Error(format("some paths in the output closure of derivation ‘%1%’ could not be repaired") % drvPath);
  792. done(BuildResult::AlreadyValid);
  793. }
  794. void DerivationGoal::inputsRealised()
  795. {
  796. trace("all inputs realised");
  797. if (nrFailed != 0) {
  798. printMsg(lvlError,
  799. format("cannot build derivation `%1%': %2% dependencies couldn't be built")
  800. % drvPath % nrFailed);
  801. done(BuildResult::DependencyFailed);
  802. return;
  803. }
  804. if (retrySubstitution) {
  805. haveDerivation();
  806. return;
  807. }
  808. /* Gather information necessary for computing the closure and/or
  809. running the build hook. */
  810. /* The outputs are referenceable paths. */
  811. foreach (DerivationOutputs::iterator, i, drv.outputs) {
  812. debug(format("building path `%1%'") % i->second.path);
  813. allPaths.insert(i->second.path);
  814. }
  815. /* Determine the full set of input paths. */
  816. /* First, the input derivations. */
  817. foreach (DerivationInputs::iterator, i, drv.inputDrvs) {
  818. /* Add the relevant output closures of the input derivation
  819. `*i' as input paths. Only add the closures of output paths
  820. that are specified as inputs. */
  821. assert(worker.store.isValidPath(i->first));
  822. Derivation inDrv = derivationFromPath(worker.store, i->first);
  823. foreach (StringSet::iterator, j, i->second)
  824. if (inDrv.outputs.find(*j) != inDrv.outputs.end())
  825. computeFSClosure(worker.store, inDrv.outputs[*j].path, inputPaths);
  826. else
  827. throw Error(
  828. format("derivation `%1%' requires non-existent output `%2%' from input derivation `%3%'")
  829. % drvPath % *j % i->first);
  830. }
  831. /* Second, the input sources. */
  832. foreach (PathSet::iterator, i, drv.inputSrcs)
  833. computeFSClosure(worker.store, *i, inputPaths);
  834. debug(format("added input paths %1%") % showPaths(inputPaths));
  835. allPaths.insert(inputPaths.begin(), inputPaths.end());
  836. /* Is this a fixed-output derivation? */
  837. fixedOutput = true;
  838. for (auto & i : drv.outputs)
  839. if (i.second.hash == "") fixedOutput = false;
  840. /* Don't repeat fixed-output derivations since they're already
  841. verified by their output hash.*/
  842. nrRounds = fixedOutput ? 1 : settings.get("build-repeat", 0) + 1;
  843. /* Okay, try to build. Note that here we don't wait for a build
  844. slot to become available, since we don't need one if there is a
  845. build hook. */
  846. state = &DerivationGoal::tryToBuild;
  847. worker.wakeUp(shared_from_this());
  848. }
  849. static bool canBuildLocally(const string & platform)
  850. {
  851. return platform == settings.thisSystem
  852. #if __linux__
  853. || (platform == "i686-linux" && settings.thisSystem == "x86_64-linux")
  854. || (platform == "armhf-linux" && settings.thisSystem == "aarch64-linux")
  855. #endif
  856. ;
  857. }
  858. static string get(const StringPairs & map, const string & key, const string & def = "")
  859. {
  860. StringPairs::const_iterator i = map.find(key);
  861. return i == map.end() ? def : i->second;
  862. }
  863. bool willBuildLocally(const Derivation & drv)
  864. {
  865. return get(drv.env, "preferLocalBuild") == "1" && canBuildLocally(drv.platform);
  866. }
  867. bool substitutesAllowed(const Derivation & drv)
  868. {
  869. return get(drv.env, "allowSubstitutes", "1") == "1";
  870. }
  871. void DerivationGoal::tryToBuild()
  872. {
  873. trace("trying to build");
  874. /* Check for the possibility that some other goal in this process
  875. has locked the output since we checked in haveDerivation().
  876. (It can't happen between here and the lockPaths() call below
  877. because we're not allowing multi-threading.) If so, put this
  878. goal to sleep until another goal finishes, then try again. */
  879. foreach (DerivationOutputs::iterator, i, drv.outputs)
  880. if (pathIsLockedByMe(i->second.path)) {
  881. debug(format("putting derivation `%1%' to sleep because `%2%' is locked by another goal")
  882. % drvPath % i->second.path);
  883. worker.waitForAnyGoal(shared_from_this());
  884. return;
  885. }
  886. /* Obtain locks on all output paths. The locks are automatically
  887. released when we exit this function or the client crashes. If we
  888. can't acquire the lock, then continue; hopefully some other
  889. goal can start a build, and if not, the main loop will sleep a
  890. few seconds and then retry this goal. */
  891. if (!outputLocks.lockPaths(outputPaths(drv), "", false)) {
  892. worker.waitForAWhile(shared_from_this());
  893. return;
  894. }
  895. /* Now check again whether the outputs are valid. This is because
  896. another process may have started building in parallel. After
  897. it has finished and released the locks, we can (and should)
  898. reuse its results. (Strictly speaking the first check can be
  899. omitted, but that would be less efficient.) Note that since we
  900. now hold the locks on the output paths, no other process can
  901. build this derivation, so no further checks are necessary. */
  902. validPaths = checkPathValidity(true, buildMode == bmRepair);
  903. if (buildMode != bmCheck && validPaths.size() == drv.outputs.size()) {
  904. debug(format("skipping build of derivation `%1%', someone beat us to it") % drvPath);
  905. outputLocks.setDeletion(true);
  906. done(BuildResult::AlreadyValid);
  907. return;
  908. }
  909. missingPaths = outputPaths(drv);
  910. if (buildMode != bmCheck)
  911. foreach (PathSet::iterator, i, validPaths) missingPaths.erase(*i);
  912. /* If any of the outputs already exist but are not valid, delete
  913. them. */
  914. foreach (DerivationOutputs::iterator, i, drv.outputs) {
  915. Path path = i->second.path;
  916. if (worker.store.isValidPath(path)) continue;
  917. if (!pathExists(path)) continue;
  918. debug(format("removing invalid path `%1%'") % path);
  919. deletePath(path);
  920. }
  921. /* Check again whether any output previously failed to build,
  922. because some other process may have tried and failed before we
  923. acquired the lock. */
  924. foreach (DerivationOutputs::iterator, i, drv.outputs)
  925. if (pathFailed(i->second.path)) return;
  926. /* Don't do a remote build if the derivation has the attribute
  927. `preferLocalBuild' set. Also, check and repair modes are only
  928. supported for local builds. */
  929. bool buildLocally = buildMode != bmNormal || willBuildLocally(drv);
  930. /* Is the build hook willing to accept this job? */
  931. if (!buildLocally) {
  932. switch (tryBuildHook()) {
  933. case rpAccept:
  934. /* Yes, it has started doing so. Wait until we get
  935. EOF from the hook. */
  936. state = &DerivationGoal::buildDone;
  937. return;
  938. case rpPostpone:
  939. /* Not now; wait until at least one child finishes or
  940. the wake-up timeout expires. */
  941. worker.waitForAWhile(shared_from_this());
  942. outputLocks.unlock();
  943. return;
  944. case rpDecline:
  945. /* We should do it ourselves. */
  946. break;
  947. }
  948. }
  949. /* Make sure that we are allowed to start a build. If this
  950. derivation prefers to be done locally, do it even if
  951. maxBuildJobs is 0. */
  952. unsigned int curBuilds = worker.getNrLocalBuilds();
  953. if (curBuilds >= settings.maxBuildJobs && !(buildLocally && curBuilds == 0)) {
  954. worker.waitForBuildSlot(shared_from_this());
  955. outputLocks.unlock();
  956. return;
  957. }
  958. try {
  959. /* Okay, we have to build. */
  960. startBuilder();
  961. } catch (BuildError & e) {
  962. printMsg(lvlError, e.msg());
  963. outputLocks.unlock();
  964. buildUser.release();
  965. if (settings.printBuildTrace)
  966. printMsg(lvlError, format("@ build-failed %1% - %2% %3%")
  967. % drvPath % 0 % e.msg());
  968. worker.permanentFailure = true;
  969. done(BuildResult::InputRejected, e.msg());
  970. return;
  971. }
  972. /* This state will be reached when we get EOF on the child's
  973. log pipe. */
  974. state = &DerivationGoal::buildDone;
  975. }
  976. void replaceValidPath(const Path & storePath, const Path tmpPath)
  977. {
  978. /* We can't atomically replace storePath (the original) with
  979. tmpPath (the replacement), so we have to move it out of the
  980. way first. We'd better not be interrupted here, because if
  981. we're repairing (say) Glibc, we end up with a broken system. */
  982. Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % rand()).str();
  983. if (pathExists(storePath))
  984. rename(storePath.c_str(), oldPath.c_str());
  985. if (rename(tmpPath.c_str(), storePath.c_str()) == -1)
  986. throw SysError(format("moving `%1%' to `%2%'") % tmpPath % storePath);
  987. if (pathExists(oldPath))
  988. deletePath(oldPath);
  989. }
  990. MakeError(NotDeterministic, BuildError)
  991. void DerivationGoal::buildDone()
  992. {
  993. trace("build done");
  994. /* Since we got an EOF on the logger pipe, the builder is presumed
  995. to have terminated. In fact, the builder could also have
  996. simply have closed its end of the pipe --- just don't do that
  997. :-) */
  998. int status;
  999. pid_t savedPid;
  1000. if (hook) {
  1001. savedPid = hook->pid;
  1002. status = hook->pid.wait(true);
  1003. } else {
  1004. /* !!! this could block! security problem! solution: kill the
  1005. child */
  1006. savedPid = pid;
  1007. status = pid.wait(true);
  1008. }
  1009. debug(format("builder process for `%1%' finished") % drvPath);
  1010. /* So the child is gone now. */
  1011. worker.childTerminated(savedPid);
  1012. /* Close the read side of the logger pipe. */
  1013. if (hook) {
  1014. hook->builderOut.readSide.close();
  1015. hook->fromAgent.readSide.close();
  1016. }
  1017. else builderOut.readSide.close();
  1018. /* Close the log file. */
  1019. closeLogFile();
  1020. /* When running under a build user, make sure that all processes
  1021. running under that uid are gone. This is to prevent a
  1022. malicious user from leaving behind a process that keeps files
  1023. open and modifies them after they have been chown'ed to
  1024. root. */
  1025. if (buildUser.enabled()) buildUser.kill();
  1026. bool diskFull = false;
  1027. try {
  1028. /* Check the exit status. */
  1029. if (!statusOk(status)) {
  1030. /* Heuristically check whether the build failure may have
  1031. been caused by a disk full condition. We have no way
  1032. of knowing whether the build actually got an ENOSPC.
  1033. So instead, check if the disk is (nearly) full now. If
  1034. so, we don't mark this build as a permanent failure. */
  1035. #if HAVE_STATVFS
  1036. unsigned long long required = 8ULL * 1024 * 1024; // FIXME: make configurable
  1037. struct statvfs st;
  1038. if (statvfs(settings.nixStore.c_str(), &st) == 0 &&
  1039. (unsigned long long) st.f_bavail * st.f_bsize < required)
  1040. diskFull = true;
  1041. if (statvfs(tmpDir.c_str(), &st) == 0 &&
  1042. (unsigned long long) st.f_bavail * st.f_bsize < required)
  1043. diskFull = true;
  1044. #endif
  1045. deleteTmpDir(false);
  1046. /* Move paths out of the chroot for easier debugging of
  1047. build failures. */
  1048. if (useChroot && buildMode == bmNormal)
  1049. foreach (PathSet::iterator, i, missingPaths)
  1050. if (pathExists(chrootRootDir + *i))
  1051. rename((chrootRootDir + *i).c_str(), i->c_str());
  1052. if (diskFull)
  1053. printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
  1054. throw BuildError(format("builder for `%1%' %2%")
  1055. % drvPath % statusToString(status));
  1056. }
  1057. /* Compute the FS closure of the outputs and register them as
  1058. being valid. */
  1059. registerOutputs();
  1060. /* Delete unused redirected outputs (when doing hash rewriting). */
  1061. foreach (RedirectedOutputs::iterator, i, redirectedOutputs)
  1062. if (pathExists(i->second)) deletePath(i->second);
  1063. /* Delete the chroot (if we were using one). */
  1064. autoDelChroot.reset(); /* this runs the destructor */
  1065. deleteTmpDir(true);
  1066. /* Repeat the build if necessary. */
  1067. if (curRound++ < nrRounds) {
  1068. outputLocks.unlock();
  1069. buildUser.release();
  1070. state = &DerivationGoal::tryToBuild;
  1071. worker.wakeUp(shared_from_this());
  1072. return;
  1073. }
  1074. /* It is now safe to delete the lock files, since all future
  1075. lockers will see that the output paths are valid; they will
  1076. not create new lock files with the same names as the old
  1077. (unlinked) lock files. */
  1078. outputLocks.setDeletion(true);
  1079. outputLocks.unlock();
  1080. } catch (BuildError & e) {
  1081. if (!hook)
  1082. printMsg(lvlError, e.msg());
  1083. outputLocks.unlock();
  1084. buildUser.release();
  1085. BuildResult::Status st = BuildResult::MiscFailure;
  1086. if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101) {
  1087. if (settings.printBuildTrace)
  1088. printMsg(lvlError, format("@ build-failed %1% - timeout") % drvPath);
  1089. st = BuildResult::TimedOut;
  1090. }
  1091. else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) {
  1092. if (settings.printBuildTrace)
  1093. printMsg(lvlError, format("@ hook-failed %1% - %2% %3%")
  1094. % drvPath % status % e.msg());
  1095. }
  1096. else {
  1097. if (settings.printBuildTrace)
  1098. printMsg(lvlError, format("@ build-failed %1% - %2% %3%")
  1099. % drvPath % 1 % e.msg());
  1100. st =
  1101. statusOk(status) ? BuildResult::OutputRejected :
  1102. fixedOutput || diskFull ? BuildResult::TransientFailure :
  1103. BuildResult::PermanentFailure;
  1104. /* Register the outputs of this build as "failed" so we
  1105. won't try to build them again (negative caching).
  1106. However, don't do this for fixed-output derivations,
  1107. since they're likely to fail for transient reasons
  1108. (e.g., fetchurl not being able to access the network).
  1109. Hook errors (like communication problems with the
  1110. remote machine) shouldn't be cached either. */
  1111. if (settings.cacheFailure && !fixedOutput && !diskFull)
  1112. foreach (DerivationOutputs::iterator, i, drv.outputs)
  1113. worker.store.registerFailedPath(i->second.path);
  1114. }
  1115. done(st, e.msg());
  1116. return;
  1117. }
  1118. /* Release the build user, if applicable. */
  1119. buildUser.release();
  1120. if (settings.printBuildTrace)
  1121. printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath);
  1122. done(BuildResult::Built);
  1123. }
  1124. HookReply DerivationGoal::tryBuildHook()
  1125. {
  1126. if (!settings.useBuildHook) return rpDecline;
  1127. if (!worker.hook) {
  1128. Strings args = {
  1129. "offload",
  1130. settings.thisSystem.c_str(),
  1131. (format("%1%") % settings.maxSilentTime).str().c_str(),
  1132. (format("%1%") % settings.printBuildTrace).str().c_str(),
  1133. (format("%1%") % settings.buildTimeout).str().c_str()
  1134. };
  1135. worker.hook = std::make_shared<Agent>(settings.guixProgram, args);
  1136. }
  1137. /* Tell the hook about system features (beyond the system type)
  1138. required from the build machine. (The hook could parse the
  1139. drv file itself, but this is easier.) */
  1140. Strings features = tokenizeString<Strings>(get(drv.env, "requiredSystemFeatures"));
  1141. foreach (Strings::iterator, i, features) checkStoreName(*i); /* !!! abuse */
  1142. /* Send the request to the hook. */
  1143. writeLine(worker.hook->toAgent.writeSide, (format("%1% %2% %3% %4%")
  1144. % (worker.getNrLocalBuilds() < settings.maxBuildJobs ? "1" : "0")
  1145. % drv.platform % drvPath % concatStringsSep(",", features)).str());
  1146. /* Read the first line of input, which should be a word indicating
  1147. whether the hook wishes to perform the build. */
  1148. string reply;
  1149. while (true) {
  1150. string s = readLine(worker.hook->fromAgent.readSide);
  1151. if (string(s, 0, 2) == "# ") {
  1152. reply = string(s, 2);
  1153. break;
  1154. }
  1155. s += "\n";
  1156. writeToStderr(s);
  1157. }
  1158. debug(format("hook reply is `%1%'") % reply);
  1159. if (reply == "decline" || reply == "postpone")
  1160. return reply == "decline" ? rpDecline : rpPostpone;
  1161. else if (reply != "accept")
  1162. throw Error(format("bad hook reply `%1%'") % reply);
  1163. printMsg(lvlTalkative, format("using hook to build path(s) %1%") % showPaths(missingPaths));
  1164. hook = worker.hook;
  1165. worker.hook.reset();
  1166. /* Tell the hook all the inputs that have to be copied to the
  1167. remote system. This unfortunately has to contain the entire
  1168. derivation closure to ensure that the validity invariant holds
  1169. on the remote system. (I.e., it's unfortunate that we have to
  1170. list it since the remote system *probably* already has it.) */
  1171. PathSet allInputs;
  1172. allInputs.insert(inputPaths.begin(), inputPaths.end());
  1173. computeFSClosure(worker.store, drvPath, allInputs);
  1174. string s;
  1175. foreach (PathSet::iterator, i, allInputs) { s += *i; s += ' '; }
  1176. writeLine(hook->toAgent.writeSide, s);
  1177. /* Tell the hooks the missing outputs that have to be copied back
  1178. from the remote system. */
  1179. s = "";
  1180. foreach (PathSet::iterator, i, missingPaths) { s += *i; s += ' '; }
  1181. writeLine(hook->toAgent.writeSide, s);
  1182. hook->toAgent.writeSide.close();
  1183. /* Create the log file and pipe. */
  1184. Path logFile = openLogFile();
  1185. set<int> fds;
  1186. fds.insert(hook->fromAgent.readSide);
  1187. fds.insert(hook->builderOut.readSide);
  1188. worker.childStarted(shared_from_this(), hook->pid, fds, false, true);
  1189. if (settings.printBuildTrace)
  1190. printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%")
  1191. % drvPath % drv.platform % logFile % hook->pid);
  1192. return rpAccept;
  1193. }
  1194. void chmod_(const Path & path, mode_t mode)
  1195. {
  1196. if (chmod(path.c_str(), mode) == -1)
  1197. throw SysError(format("setting permissions on `%1%'") % path);
  1198. }
  1199. int childEntry(void * arg)
  1200. {
  1201. ((DerivationGoal *) arg)->runChild();
  1202. return 1;
  1203. }
  1204. void DerivationGoal::startBuilder()
  1205. {
  1206. auto f = format(
  1207. buildMode == bmRepair ? "repairing path(s) %1%" :
  1208. buildMode == bmCheck ? "checking path(s) %1%" :
  1209. nrRounds > 1 ? "building path(s) %1% (round %2%/%3%)" :
  1210. "building path(s) %1%");
  1211. f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
  1212. startNest(nest, lvlInfo, f % showPaths(missingPaths) % curRound % nrRounds);
  1213. /* Note: built-in builders are *not* running in a chroot environment so
  1214. that we can easily implement them in Guile without having it as a
  1215. derivation input (they are running under a separate build user,
  1216. though). */
  1217. useChroot = settings.useChroot && !isBuiltin(drv);
  1218. /* Construct the environment passed to the builder. */
  1219. env.clear();
  1220. /* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
  1221. PATH is not set. We don't want this, so we fill it in with some dummy
  1222. value. */
  1223. env["PATH"] = "/path-not-set";
  1224. /* Set HOME to a non-existing path to prevent certain programs from using
  1225. /etc/passwd (or NIS, or whatever) to locate the home directory (for
  1226. example, wget looks for ~/.wgetrc). I.e., these tools use /etc/passwd
  1227. if HOME is not set, but they will just assume that the settings file
  1228. they are looking for does not exist if HOME is set but points to some
  1229. non-existing path. */
  1230. Path homeDir = "/homeless-shelter";
  1231. env["HOME"] = homeDir;
  1232. /* Tell the builder where the store is. Usually they
  1233. shouldn't care, but this is useful for purity checking (e.g.,
  1234. the compiler or linker might only want to accept paths to files
  1235. in the store or in the build directory). */
  1236. env["NIX_STORE"] = settings.nixStore;
  1237. /* The maximum number of cores to utilize for parallel building. */
  1238. env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
  1239. /* Add all bindings specified in the derivation. */
  1240. foreach (StringPairs::iterator, i, drv.env)
  1241. env[i->first] = i->second;
  1242. /* Create a temporary directory where the build will take
  1243. place. */
  1244. auto drvName = storePathToName(drvPath);
  1245. tmpDir = createTempDir("", "guix-build-" + drvName, false, false, 0700);
  1246. if (useChroot) {
  1247. /* Make the build directory seen by the build process a sub-directory.
  1248. That way, "/tmp/guix-build-foo.drv-0" is root-owned, and thus its
  1249. permissions cannot be changed by the build process, while
  1250. "/tmp/guix-build-foo.drv-0/top" is owned by the build user. This
  1251. cannot be done when !useChroot because then $NIX_BUILD_TOP would
  1252. be inaccessible to the build user by its full file name.
  1253. If the build user could make the build directory world-writable,
  1254. then an attacker could create in it a hardlink to a root-owned file
  1255. such as /etc/shadow. If 'keepFailed' is true, the daemon would
  1256. then chown that hardlink to the user, giving them write access to
  1257. that file. */
  1258. tmpDir += "/top";
  1259. if (mkdir(tmpDir.c_str(), 0700) == 1)
  1260. throw SysError("creating top-level build directory");
  1261. }
  1262. /* In a sandbox, for determinism, always use the same temporary
  1263. directory. */
  1264. tmpDirInSandbox = useChroot ? canonPath("/tmp", true) + "/guix-build-" + drvName + "-0" : tmpDir;
  1265. /* For convenience, set an environment pointing to the top build
  1266. directory. */
  1267. env["NIX_BUILD_TOP"] = tmpDirInSandbox;
  1268. /* Also set TMPDIR and variants to point to this directory. */
  1269. env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDirInSandbox;
  1270. /* Explicitly set PWD to prevent problems with chroot builds. In
  1271. particular, dietlibc cannot figure out the cwd because the
  1272. inode of the current directory doesn't appear in .. (because
  1273. getdents returns the inode of the mount point). */
  1274. env["PWD"] = tmpDirInSandbox;
  1275. /* *Only* if this is a fixed-output derivation, propagate the
  1276. values of the environment variables specified in the
  1277. `impureEnvVars' attribute to the builder. This allows for
  1278. instance environment variables for proxy configuration such as
  1279. `http_proxy' to be easily passed to downloaders like
  1280. `fetchurl'. Passing such environment variables from the caller
  1281. to the builder is generally impure, but the output of
  1282. fixed-output derivations is by definition pure (since we
  1283. already know the cryptographic hash of the output). */
  1284. if (fixedOutput) {
  1285. Strings varNames = tokenizeString<Strings>(get(drv.env, "impureEnvVars"));
  1286. foreach (Strings::iterator, i, varNames) env[*i] = getEnv(*i);
  1287. }
  1288. /* The `exportReferencesGraph' feature allows the references graph
  1289. to be passed to a builder. This attribute should be a list of
  1290. pairs [name1 path1 name2 path2 ...]. The references graph of
  1291. each `pathN' will be stored in a text file `nameN' in the
  1292. temporary build directory. The text files have the format used
  1293. by `nix-store --register-validity'. However, the deriver
  1294. fields are left empty. */
  1295. string s = get(drv.env, "exportReferencesGraph");
  1296. Strings ss = tokenizeString<Strings>(s);
  1297. if (ss.size() % 2 != 0)
  1298. throw BuildError(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s);
  1299. for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
  1300. string fileName = *i++;
  1301. checkStoreName(fileName); /* !!! abuse of this function */
  1302. /* Check that the store path is valid. */
  1303. Path storePath = *i++;
  1304. if (!isInStore(storePath))
  1305. throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'")
  1306. % storePath);
  1307. storePath = toStorePath(storePath);
  1308. if (!worker.store.isValidPath(storePath))
  1309. throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'")
  1310. % storePath);
  1311. /* If there are derivations in the graph, then include their
  1312. outputs as well. This is useful if you want to do things
  1313. like passing all build-time dependencies of some path to a
  1314. derivation that builds a NixOS DVD image. */
  1315. PathSet paths, paths2;
  1316. computeFSClosure(worker.store, storePath, paths);
  1317. paths2 = paths;
  1318. foreach (PathSet::iterator, j, paths2) {
  1319. if (isDerivation(*j)) {
  1320. Derivation drv = derivationFromPath(worker.store, *j);
  1321. foreach (DerivationOutputs::iterator, k, drv.outputs)
  1322. computeFSClosure(worker.store, k->second.path, paths);
  1323. }
  1324. }
  1325. /* Write closure info to `fileName'. */
  1326. writeFile(tmpDir + "/" + fileName,
  1327. worker.store.makeValidityRegistration(paths, false, false));
  1328. }
  1329. /* If `build-users-group' is not empty, then we have to build as
  1330. one of the members of that group. */
  1331. if (settings.buildUsersGroup != "") {
  1332. buildUser.acquire();
  1333. assert(buildUser.getUID() != 0);
  1334. assert(buildUser.getGID() != 0);
  1335. /* Make sure that no other processes are executing under this
  1336. uid. */
  1337. buildUser.kill();
  1338. /* Change ownership of the temporary build directory. */
  1339. if (chown(tmpDir.c_str(), buildUser.getUID(), buildUser.getGID()) == -1)
  1340. throw SysError(format("cannot change ownership of '%1%'") % tmpDir);
  1341. }
  1342. if (useChroot) {
  1343. #if CHROOT_ENABLED
  1344. /* Create a temporary directory in which we set up the chroot
  1345. environment using bind-mounts. We put it in the store
  1346. to ensure that we can create hard-links to non-directory
  1347. inputs in the fake store in the chroot (see below). */
  1348. chrootRootDir = drvPath + ".chroot";
  1349. if (pathExists(chrootRootDir)) deletePath(chrootRootDir);
  1350. /* Clean up the chroot directory automatically. */
  1351. autoDelChroot = std::shared_ptr<AutoDelete>(new AutoDelete(chrootRootDir));
  1352. printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir);
  1353. if (mkdir(chrootRootDir.c_str(), 0750) == -1)
  1354. throw SysError(format("cannot create ‘%1%’") % chrootRootDir);
  1355. if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1)
  1356. throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir);
  1357. /* Create a writable /tmp in the chroot. Many builders need
  1358. this. (Of course they should really respect $TMPDIR
  1359. instead.) */
  1360. Path chrootTmpDir = chrootRootDir + "/tmp";
  1361. createDirs(chrootTmpDir);
  1362. chmod_(chrootTmpDir, 01777);
  1363. /* Create a /etc/passwd with entries for the build user and the
  1364. nobody account. The latter is kind of a hack to support
  1365. Samba-in-QEMU. */
  1366. createDirs(chrootRootDir + "/etc");
  1367. writeFile(chrootRootDir + "/etc/passwd",
  1368. (format(
  1369. "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n"
  1370. "nobody:x:65534:65534:Nobody:/:/noshell\n")
  1371. % (buildUser.enabled() ? buildUser.getUID() : getuid())
  1372. % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
  1373. /* Declare the build user's group so that programs get a consistent
  1374. view of the system (e.g., "id -gn"). */
  1375. writeFile(chrootRootDir + "/etc/group",
  1376. (format("nixbld:!:%1%:\n")
  1377. % (buildUser.enabled() ? buildUser.getGID() : getgid())).str());
  1378. /* Create /etc/hosts with localhost entry. */
  1379. if (!fixedOutput)
  1380. writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n");
  1381. /* Bind-mount a user-configurable set of directories from the
  1382. host file system. */
  1383. PathSet dirs = tokenizeString<StringSet>(settings.get("build-chroot-dirs", string(DEFAULT_CHROOT_DIRS)));
  1384. PathSet dirs2 = tokenizeString<StringSet>(settings.get("build-extra-chroot-dirs", string("")));
  1385. dirs.insert(dirs2.begin(), dirs2.end());
  1386. for (auto & i : dirs) {
  1387. size_t p = i.find('=');
  1388. if (p == string::npos)
  1389. dirsInChroot[i] = i;
  1390. else
  1391. dirsInChroot[string(i, 0, p)] = string(i, p + 1);
  1392. }
  1393. dirsInChroot[tmpDirInSandbox] = tmpDir;
  1394. /* Make the closure of the inputs available in the chroot,
  1395. rather than the whole store. This prevents any access
  1396. to undeclared dependencies. Directories are bind-mounted,
  1397. while other inputs are hard-linked (since only directories
  1398. can be bind-mounted). !!! As an extra security
  1399. precaution, make the fake store only writable by the
  1400. build user. */
  1401. Path chrootStoreDir = chrootRootDir + settings.nixStore;
  1402. createDirs(chrootStoreDir);
  1403. chmod_(chrootStoreDir, 01775);
  1404. if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1)
  1405. throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir);
  1406. foreach (PathSet::iterator, i, inputPaths) {
  1407. struct stat st;
  1408. if (lstat(i->c_str(), &st))
  1409. throw SysError(format("getting attributes of path `%1%'") % *i);
  1410. if (S_ISDIR(st.st_mode))
  1411. dirsInChroot[*i] = *i;
  1412. else {
  1413. Path p = chrootRootDir + *i;
  1414. if (link(i->c_str(), p.c_str()) == -1) {
  1415. /* Hard-linking fails if we exceed the maximum
  1416. link count on a file (e.g. 32000 of ext3),
  1417. which is quite possible after a `nix-store
  1418. --optimise'. */
  1419. if (errno != EMLINK)
  1420. throw SysError(format("linking `%1%' to `%2%'") % p % *i);
  1421. StringSink sink;
  1422. dumpPath(*i, sink);
  1423. StringSource source(sink.s);
  1424. restorePath(p, source);
  1425. }
  1426. regularInputPaths.insert(*i);
  1427. }
  1428. }
  1429. /* If we're repairing, checking or rebuilding part of a
  1430. multiple-outputs derivation, it's possible that we're
  1431. rebuilding a path that is in settings.dirsInChroot
  1432. (typically the dependencies of /bin/sh). Throw them
  1433. out. */
  1434. for (auto & i : drv.outputs)
  1435. dirsInChroot.erase(i.second.path);
  1436. #else
  1437. throw Error("chroot builds are not supported on this platform");
  1438. #endif
  1439. }
  1440. else {
  1441. if (pathExists(homeDir))
  1442. throw Error(format("directory `%1%' exists; please remove it") % homeDir);
  1443. /* We're not doing a chroot build, but we have some valid
  1444. output paths. Since we can't just overwrite or delete
  1445. them, we have to do hash rewriting: i.e. in the
  1446. environment/arguments passed to the build, we replace the
  1447. hashes of the valid outputs with unique dummy strings;
  1448. after the build, we discard the redirected outputs
  1449. corresponding to the valid outputs, and rewrite the
  1450. contents of the new outputs to replace the dummy strings
  1451. with the actual hashes. */
  1452. if (validPaths.size() > 0)
  1453. foreach (PathSet::iterator, i, validPaths)
  1454. addHashRewrite(*i);
  1455. /* If we're repairing, then we don't want to delete the
  1456. corrupt outputs in advance. So rewrite them as well. */
  1457. if (buildMode == bmRepair)
  1458. foreach (PathSet::iterator, i, missingPaths)
  1459. if (worker.store.isValidPath(*i) && pathExists(*i)) {
  1460. addHashRewrite(*i);
  1461. redirectedBadOutputs.insert(*i);
  1462. }
  1463. }
  1464. /* Run the builder. */
  1465. printMsg(lvlChatty, format("executing builder `%1%'") % drv.builder);
  1466. /* Create the log file. */
  1467. Path logFile = openLogFile();
  1468. /* Create a pipe to get the output of the builder. */
  1469. builderOut.create();
  1470. /* Fork a child to build the package. Note that while we
  1471. currently use forks to run and wait for the children, it
  1472. shouldn't be hard to use threads for this on systems where
  1473. fork() is unavailable or inefficient.
  1474. If we're building in a chroot, then also set up private
  1475. namespaces for the build:
  1476. - The PID namespace causes the build to start as PID 1.
  1477. Processes outside of the chroot are not visible to those on
  1478. the inside, but processes inside the chroot are visible from
  1479. the outside (though with different PIDs).
  1480. - The private mount namespace ensures that all the bind mounts
  1481. we do will only show up in this process and its children, and
  1482. will disappear automatically when we're done.
  1483. - The private network namespace ensures that the builder cannot
  1484. talk to the outside world (or vice versa). It only has a
  1485. private loopback interface.
  1486. - The IPC namespace prevents the builder from communicating
  1487. with outside processes using SysV IPC mechanisms (shared
  1488. memory, message queues, semaphores). It also ensures that
  1489. all IPC objects are destroyed when the builder exits.
  1490. - The UTS namespace ensures that builders see a hostname of
  1491. localhost rather than the actual hostname.
  1492. */
  1493. #if __linux__
  1494. if (useChroot) {
  1495. char stack[32 * 1024];
  1496. int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD;
  1497. if (!fixedOutput) flags |= CLONE_NEWNET;
  1498. /* Ensure proper alignment on the stack. On aarch64, it has to be 16
  1499. bytes. */
  1500. pid = clone(childEntry,
  1501. (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf),
  1502. flags, this);
  1503. if (pid == -1)
  1504. throw SysError("cloning builder process");
  1505. } else
  1506. #endif
  1507. {
  1508. pid = fork();
  1509. if (pid == 0) runChild();
  1510. }
  1511. if (pid == -1) throw SysError("unable to fork");
  1512. /* parent */
  1513. pid.setSeparatePG(true);
  1514. builderOut.writeSide.close();
  1515. worker.childStarted(shared_from_this(), pid,
  1516. singleton<set<int> >(builderOut.readSide), true, true);
  1517. /* Check if setting up the build environment failed. */
  1518. string msg = readLine(builderOut.readSide);
  1519. if (!msg.empty()) throw Error(msg);
  1520. if (settings.printBuildTrace) {
  1521. printMsg(lvlError, format("@ build-started %1% - %2% %3% %4%")
  1522. % drvPath % drv.platform % logFile % pid);
  1523. }
  1524. }
  1525. /* Return true if the operating system kernel part of SYSTEM1 and SYSTEM2 (the
  1526. bit that comes after the hyphen in system types such as "i686-linux") is
  1527. the same. */
  1528. static bool sameOperatingSystemKernel(const std::string& system1, const std::string& system2)
  1529. {
  1530. auto os1 = system1.substr(system1.find("-"));
  1531. auto os2 = system2.substr(system2.find("-"));
  1532. return os1 == os2;
  1533. }
  1534. void DerivationGoal::runChild()
  1535. {
  1536. /* Warning: in the child we should absolutely not make any SQLite
  1537. calls! */
  1538. try { /* child */
  1539. _writeToStderr = 0;
  1540. restoreAffinity();
  1541. commonChildInit(builderOut);
  1542. #if CHROOT_ENABLED
  1543. if (useChroot) {
  1544. /* Initialise the loopback interface. */
  1545. AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP));
  1546. if (fd == -1) throw SysError("cannot open IP socket");
  1547. struct ifreq ifr;
  1548. strcpy(ifr.ifr_name, "lo");
  1549. ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
  1550. if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1)
  1551. throw SysError("cannot set loopback interface flags");
  1552. fd.close();
  1553. /* Set the hostname etc. to fixed values. */
  1554. char hostname[] = "localhost";
  1555. if (sethostname(hostname, sizeof(hostname)) == -1)
  1556. throw SysError("cannot set host name");
  1557. char domainname[] = "(none)"; // kernel default
  1558. if (setdomainname(domainname, sizeof(domainname)) == -1)
  1559. throw SysError("cannot set domain name");
  1560. /* Make all filesystems private. This is necessary
  1561. because subtrees may have been mounted as "shared"
  1562. (MS_SHARED). (Systemd does this, for instance.) Even
  1563. though we have a private mount namespace, mounting
  1564. filesystems on top of a shared subtree still propagates
  1565. outside of the namespace. Making a subtree private is
  1566. local to the namespace, though, so setting MS_PRIVATE
  1567. does not affect the outside world. */
  1568. if (mount(0, "/", 0, MS_REC|MS_PRIVATE, 0) == -1) {
  1569. throw SysError("unable to make ‘/’ private mount");
  1570. }
  1571. /* Bind-mount chroot directory to itself, to treat it as a
  1572. different filesystem from /, as needed for pivot_root. */
  1573. if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0, MS_BIND, 0) == -1)
  1574. throw SysError(format("unable to bind mount ‘%1%’") % chrootRootDir);
  1575. /* Set up a nearly empty /dev, unless the user asked to
  1576. bind-mount the host /dev. */
  1577. Strings ss;
  1578. if (dirsInChroot.find("/dev") == dirsInChroot.end()) {
  1579. createDirs(chrootRootDir + "/dev/shm");
  1580. createDirs(chrootRootDir + "/dev/pts");
  1581. ss.push_back("/dev/full");
  1582. #ifdef __linux__
  1583. if (pathExists("/dev/kvm"))
  1584. ss.push_back("/dev/kvm");
  1585. #endif
  1586. ss.push_back("/dev/null");
  1587. ss.push_back("/dev/random");
  1588. ss.push_back("/dev/tty");
  1589. ss.push_back("/dev/urandom");
  1590. ss.push_back("/dev/zero");
  1591. createSymlink("/proc/self/fd", chrootRootDir + "/dev/fd");
  1592. createSymlink("/proc/self/fd/0", chrootRootDir + "/dev/stdin");
  1593. createSymlink("/proc/self/fd/1", chrootRootDir + "/dev/stdout");
  1594. createSymlink("/proc/self/fd/2", chrootRootDir + "/dev/stderr");
  1595. }
  1596. /* Fixed-output derivations typically need to access the
  1597. network, so give them access to /etc/resolv.conf and so
  1598. on. */
  1599. if (fixedOutput) {
  1600. ss.push_back("/etc/resolv.conf");
  1601. ss.push_back("/etc/nsswitch.conf");
  1602. ss.push_back("/etc/services");
  1603. ss.push_back("/etc/hosts");
  1604. }
  1605. for (auto & i : ss) dirsInChroot[i] = i;
  1606. /* Bind-mount all the directories from the "host"
  1607. filesystem that we want in the chroot
  1608. environment. */
  1609. foreach (DirsInChroot::iterator, i, dirsInChroot) {
  1610. struct stat st;
  1611. Path source = i->second;
  1612. Path target = chrootRootDir + i->first;
  1613. if (source == "/proc") continue; // backwards compatibility
  1614. debug(format("bind mounting `%1%' to `%2%'") % source % target);
  1615. if (stat(source.c_str(), &st) == -1)
  1616. throw SysError(format("getting attributes of path `%1%'") % source);
  1617. if (S_ISDIR(st.st_mode))
  1618. createDirs(target);
  1619. else {
  1620. createDirs(dirOf(target));
  1621. writeFile(target, "");
  1622. }
  1623. if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1)
  1624. throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target);
  1625. }
  1626. /* Bind a new instance of procfs on /proc to reflect our
  1627. private PID namespace. */
  1628. createDirs(chrootRootDir + "/proc");
  1629. if (mount("none", (chrootRootDir + "/proc").c_str(), "proc", 0, 0) == -1)
  1630. throw SysError("mounting /proc");
  1631. /* Mount a new tmpfs on /dev/shm to ensure that whatever
  1632. the builder puts in /dev/shm is cleaned up automatically. */
  1633. if (pathExists("/dev/shm") && mount("none", (chrootRootDir + "/dev/shm").c_str(), "tmpfs", 0, 0) == -1)
  1634. throw SysError("mounting /dev/shm");
  1635. /* Mount a new devpts on /dev/pts. Note that this
  1636. requires the kernel to be compiled with
  1637. CONFIG_DEVPTS_MULTIPLE_INSTANCES=y (which is the case
  1638. if /dev/ptx/ptmx exists). */
  1639. if (pathExists("/dev/pts/ptmx") &&
  1640. !pathExists(chrootRootDir + "/dev/ptmx")
  1641. && dirsInChroot.find("/dev/pts") == dirsInChroot.end())
  1642. {
  1643. if (mount("none", (chrootRootDir + "/dev/pts").c_str(), "devpts", 0, "newinstance,mode=0620") == -1)
  1644. throw SysError("mounting /dev/pts");
  1645. createSymlink("/dev/pts/ptmx", chrootRootDir + "/dev/ptmx");
  1646. /* Make sure /dev/pts/ptmx is world-writable. With some
  1647. Linux versions, it is created with permissions 0. */
  1648. chmod_(chrootRootDir + "/dev/pts/ptmx", 0666);
  1649. }
  1650. /* Do the chroot(). */
  1651. if (chdir(chrootRootDir.c_str()) == -1)
  1652. throw SysError(format("cannot change directory to '%1%'") % chrootRootDir);
  1653. if (mkdir("real-root", 0) == -1)
  1654. throw SysError("cannot create real-root directory");
  1655. if (pivot_root(".", "real-root") == -1)
  1656. throw SysError(format("cannot pivot old root directory onto '%1%'") % (chrootRootDir + "/real-root"));
  1657. if (chroot(".") == -1)
  1658. throw SysError(format("cannot change root directory to '%1%'") % chrootRootDir);
  1659. if (umount2("real-root", MNT_DETACH) == -1)
  1660. throw SysError("cannot unmount real root filesystem");
  1661. if (rmdir("real-root") == -1)
  1662. throw SysError("cannot remove real-root directory");
  1663. }
  1664. #endif
  1665. if (chdir(tmpDirInSandbox.c_str()) == -1)
  1666. throw SysError(format("changing into `%1%'") % tmpDir);
  1667. /* Close all other file descriptors. */
  1668. closeMostFDs(set<int>());
  1669. #if __linux__
  1670. /* Change the personality to 32-bit if we're doing an
  1671. i686-linux build on an x86_64-linux machine. */
  1672. struct utsname utsbuf;
  1673. uname(&utsbuf);
  1674. if (drv.platform == "i686-linux" &&
  1675. (settings.thisSystem == "x86_64-linux" ||
  1676. (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "x86_64")))) {
  1677. if (personality(PER_LINUX32) == -1)
  1678. throw SysError("cannot set i686-linux personality");
  1679. }
  1680. if (drv.platform == "armhf-linux" &&
  1681. (settings.thisSystem == "aarch64-linux" ||
  1682. (!strcmp(utsbuf.sysname, "Linux") && !strcmp(utsbuf.machine, "aarch64")))) {
  1683. if (personality(PER_LINUX32) == -1)
  1684. throw SysError("cannot set armhf-linux personality");
  1685. }
  1686. /* Impersonate a Linux 2.6 machine to get some determinism in
  1687. builds that depend on the kernel version. */
  1688. if ((drv.platform == "i686-linux" || drv.platform == "x86_64-linux") && settings.impersonateLinux26) {
  1689. int cur = personality(0xffffffff);
  1690. if (cur != -1) personality(cur | 0x0020000 /* == UNAME26 */);
  1691. }
  1692. /* Disable address space randomization for improved
  1693. determinism. */
  1694. int cur = personality(0xffffffff);
  1695. if (cur != -1) personality(cur | ADDR_NO_RANDOMIZE);
  1696. #endif
  1697. /* Fill in the environment. */
  1698. Strings envStrs;
  1699. foreach (Environment::const_iterator, i, env)
  1700. envStrs.push_back(rewriteHashes(i->first + "=" + i->second, rewritesToTmp));
  1701. /* If we are running in `build-users' mode, then switch to the
  1702. user we allocated above. Make sure that we drop all root
  1703. privileges. Note that above we have closed all file
  1704. descriptors except std*, so that's safe. Also note that
  1705. setuid() when run as root sets the real, effective and
  1706. saved UIDs. */
  1707. if (buildUser.enabled()) {
  1708. /* Preserve supplementary groups of the build user, to allow
  1709. admins to specify groups such as "kvm". */
  1710. if (setgroups(buildUser.getSupplementaryGIDs().size(),
  1711. buildUser.getSupplementaryGIDs().data()) == -1)
  1712. throw SysError("cannot set supplementary groups of build user");
  1713. if (setgid(buildUser.getGID()) == -1 ||
  1714. getgid() != buildUser.getGID() ||
  1715. getegid() != buildUser.getGID())
  1716. throw SysError("setgid failed");
  1717. if (setuid(buildUser.getUID()) == -1 ||
  1718. getuid() != buildUser.getUID() ||
  1719. geteuid() != buildUser.getUID())
  1720. throw SysError("setuid failed");
  1721. }
  1722. restoreSIGPIPE();
  1723. /* Indicate that we managed to set up the build environment. */
  1724. writeFull(STDERR_FILENO, "\n");
  1725. /* Execute the program. This should not return. */
  1726. if (isBuiltin(drv)) {
  1727. try {
  1728. logType = ltFlat;
  1729. auto buildDrv = lookupBuiltinBuilder(drv.builder);
  1730. if (buildDrv != NULL) {
  1731. /* Check what the output file name is. When doing a
  1732. 'bmCheck' build, the output file name is different from
  1733. that specified in DRV due to hash rewriting. */
  1734. Path output = drv.outputs["out"].path;
  1735. auto redirected = redirectedOutputs.find(output);
  1736. if (redirected != redirectedOutputs.end())
  1737. output = redirected->second;
  1738. buildDrv(drv, drvPath, output);
  1739. }
  1740. else
  1741. throw Error(format("unsupported builtin function '%1%'") % string(drv.builder, 8));
  1742. _exit(0);
  1743. } catch (std::exception & e) {
  1744. writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
  1745. _exit(1);
  1746. }
  1747. }
  1748. /* Fill in the arguments. */
  1749. Strings args;
  1750. string builderBasename = baseNameOf(drv.builder);
  1751. args.push_back(builderBasename);
  1752. foreach (Strings::iterator, i, drv.args)
  1753. args.push_back(rewriteHashes(*i, rewritesToTmp));
  1754. /* If DRV targets the same operating system kernel, try to execute it:
  1755. there might be binfmt_misc set up for user-land emulation of other
  1756. architectures. However, if it targets a different operating
  1757. system--e.g., "i586-gnu" vs. "x86_64-linux"--do not try executing
  1758. it: the ELF file for that OS is likely indistinguishable from a
  1759. native ELF binary and it would just crash at run time. */
  1760. int error;
  1761. if (sameOperatingSystemKernel(drv.platform, settings.thisSystem)) {
  1762. execve(drv.builder.c_str(), stringsToCharPtrs(args).data(),
  1763. stringsToCharPtrs(envStrs).data());
  1764. error = errno;
  1765. } else {
  1766. error = ENOEXEC;
  1767. }
  1768. /* Right platform? Check this after we've tried 'execve' to allow for
  1769. transparent emulation of different platforms with binfmt_misc
  1770. handlers that invoke QEMU. */
  1771. if (error == ENOEXEC && !canBuildLocally(drv.platform)) {
  1772. if (settings.printBuildTrace)
  1773. printMsg(lvlError, format("@ unsupported-platform %1% %2%") % drvPath % drv.platform);
  1774. throw Error(
  1775. format("a `%1%' is required to build `%3%', but I am a `%2%'")
  1776. % drv.platform % settings.thisSystem % drvPath);
  1777. }
  1778. errno = error;
  1779. throw SysError(format("executing `%1%'") % drv.builder);
  1780. } catch (std::exception & e) {
  1781. writeFull(STDERR_FILENO, "while setting up the build environment: " + string(e.what()) + "\n");
  1782. _exit(1);
  1783. }
  1784. abort(); /* never reached */
  1785. }
  1786. /* Parse a list of reference specifiers. Each element must either be
  1787. a store path, or the symbolic name of the output of the derivation
  1788. (such as `out'). */
  1789. PathSet parseReferenceSpecifiers(const Derivation & drv, string attr)
  1790. {
  1791. PathSet result;
  1792. Paths paths = tokenizeString<Paths>(attr);
  1793. foreach (Strings::iterator, i, paths) {
  1794. if (isStorePath(*i))
  1795. result.insert(*i);
  1796. else if (drv.outputs.find(*i) != drv.outputs.end())
  1797. result.insert(drv.outputs.find(*i)->second.path);
  1798. else throw BuildError(
  1799. format("derivation contains an invalid reference specifier `%1%'")
  1800. % *i);
  1801. }
  1802. return result;
  1803. }
  1804. void DerivationGoal::registerOutputs()
  1805. {
  1806. /* When using a build hook, the build hook can register the output
  1807. as valid (by doing `nix-store --import'). If so we don't have
  1808. to do anything here. */
  1809. if (hook) {
  1810. bool allValid = true;
  1811. foreach (DerivationOutputs::iterator, i, drv.outputs)
  1812. if (!worker.store.isValidPath(i->second.path)) allValid = false;
  1813. if (allValid) return;
  1814. }
  1815. ValidPathInfos infos;
  1816. /* Set of inodes seen during calls to canonicalisePathMetaData()
  1817. for this build's outputs. This needs to be shared between
  1818. outputs to allow hard links between outputs. */
  1819. InodesSeen inodesSeen;
  1820. Path checkSuffix = "-check";
  1821. /* Check whether the output paths were created, and grep each
  1822. output path to determine what other paths it references. Also make all
  1823. output paths read-only. */
  1824. foreach (DerivationOutputs::iterator, i, drv.outputs) {
  1825. Path path = i->second.path;
  1826. if (missingPaths.find(path) == missingPaths.end()) continue;
  1827. Path actualPath = path;
  1828. if (useChroot) {
  1829. actualPath = chrootRootDir + path;
  1830. if (pathExists(actualPath)) {
  1831. /* Move output paths from the chroot to the store. */
  1832. if (buildMode == bmRepair)
  1833. replaceValidPath(path, actualPath);
  1834. else
  1835. if (buildMode != bmCheck && rename(actualPath.c_str(), path.c_str()) == -1)
  1836. throw SysError(format("moving build output `%1%' from the chroot to the store") % path);
  1837. }
  1838. if (buildMode != bmCheck) actualPath = path;
  1839. } else {
  1840. Path redirected = redirectedOutputs[path];
  1841. if (buildMode == bmRepair
  1842. && redirectedBadOutputs.find(path) != redirectedBadOutputs.end()
  1843. && pathExists(redirected))
  1844. replaceValidPath(path, redirected);
  1845. if (buildMode == bmCheck && redirected != "")
  1846. actualPath = redirected;
  1847. }
  1848. struct stat st;
  1849. if (lstat(actualPath.c_str(), &st) == -1) {
  1850. if (errno == ENOENT)
  1851. throw BuildError(
  1852. format("builder for `%1%' failed to produce output path `%2%'")
  1853. % drvPath % path);
  1854. throw SysError(format("getting attributes of path `%1%'") % actualPath);
  1855. }
  1856. #ifndef __CYGWIN__
  1857. /* Check that the output is not group or world writable, as
  1858. that means that someone else can have interfered with the
  1859. build. Also, the output should be owned by the build
  1860. user. */
  1861. if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) ||
  1862. (buildUser.enabled() && st.st_uid != buildUser.getUID()))
  1863. throw BuildError(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path);
  1864. #endif
  1865. /* Apply hash rewriting if necessary. */
  1866. bool rewritten = false;
  1867. if (!rewritesFromTmp.empty()) {
  1868. printMsg(lvlError, format("warning: rewriting hashes in `%1%'; cross fingers") % path);
  1869. /* Canonicalise first. This ensures that the path we're
  1870. rewriting doesn't contain a hard link to /etc/shadow or
  1871. something like that. */
  1872. canonicalisePathMetaData(actualPath, buildUser.enabled() ? buildUser.getUID() : -1, inodesSeen);
  1873. /* FIXME: this is in-memory. */
  1874. StringSink sink;
  1875. dumpPath(actualPath, sink);
  1876. deletePath(actualPath);
  1877. sink.s = rewriteHashes(sink.s, rewritesFromTmp);
  1878. StringSource source(sink.s);
  1879. restorePath(actualPath, source);
  1880. rewritten = true;
  1881. }
  1882. startNest(nest, lvlTalkative,
  1883. format("scanning for references inside `%1%'") % path);
  1884. /* Check that fixed-output derivations produced the right
  1885. outputs (i.e., the content hash should match the specified
  1886. hash). */
  1887. if (i->second.hash != "") {
  1888. bool recursive; HashType ht; Hash h;
  1889. i->second.parseHashInfo(recursive, ht, h);
  1890. if (!recursive) {
  1891. /* The output path should be a regular file without
  1892. execute permission. */
  1893. if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
  1894. throw BuildError(
  1895. format("output path `%1% should be a non-executable regular file") % path);
  1896. }
  1897. /* Check the hash. */
  1898. Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
  1899. if (h != h2) {
  1900. if (settings.printBuildTrace)
  1901. printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%")
  1902. % path % i->second.hashAlgo
  1903. % printHash16or32(h) % printHash16or32(h2));
  1904. throw BuildError(format("hash mismatch for store item '%1%'") % path);
  1905. }
  1906. }
  1907. /* Get rid of all weird permissions. This also checks that
  1908. all files are owned by the build user, if applicable. */
  1909. canonicalisePathMetaData(actualPath,
  1910. buildUser.enabled() && !rewritten ? buildUser.getUID() : -1, inodesSeen);
  1911. /* For this output path, find the references to other paths
  1912. contained in it. Compute the SHA-256 NAR hash at the same
  1913. time. The hash is stored in the database so that we can
  1914. verify later on whether nobody has messed with the store. */
  1915. HashResult hash;
  1916. PathSet references = scanForReferences(actualPath, allPaths, hash);
  1917. if (buildMode == bmCheck) {
  1918. if (!store->isValidPath(path)) continue;
  1919. ValidPathInfo info = worker.store.queryPathInfo(path);
  1920. if (hash.first != info.hash) {
  1921. if (settings.keepFailed) {
  1922. Path dst = path + checkSuffix;
  1923. if (pathExists(dst)) deletePath(dst);
  1924. if (rename(actualPath.c_str(), dst.c_str()))
  1925. throw SysError(format("renaming `%1%' to `%2%'") % actualPath % dst);
  1926. throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs from ‘%3%’")
  1927. % drvPath % path % dst);
  1928. } else
  1929. throw Error(format("derivation `%1%' may not be deterministic: output `%2%' differs")
  1930. % drvPath % path);
  1931. }
  1932. if (settings.printBuildTrace)
  1933. printMsg(lvlError, format("@ build-succeeded %1% -") % drvPath);
  1934. continue;
  1935. }
  1936. /* For debugging, print out the referenced and unreferenced
  1937. paths. */
  1938. foreach (PathSet::iterator, i, inputPaths) {
  1939. PathSet::iterator j = references.find(*i);
  1940. if (j == references.end())
  1941. debug(format("unreferenced input: `%1%'") % *i);
  1942. else
  1943. debug(format("referenced input: `%1%'") % *i);
  1944. }
  1945. /* Enforce `allowedReferences' and friends. */
  1946. auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) {
  1947. if (drv.env.find(attrName) == drv.env.end()) return;
  1948. PathSet spec = parseReferenceSpecifiers(drv, get(drv.env, attrName));
  1949. PathSet used;
  1950. if (recursive) {
  1951. /* Our requisites are the union of the closures of our references. */
  1952. for (auto & i : references)
  1953. /* Don't call computeFSClosure on ourselves. */
  1954. if (actualPath != i)
  1955. computeFSClosure(worker.store, i, used);
  1956. } else
  1957. used = references;
  1958. for (auto & i : used)
  1959. if (allowed) {
  1960. if (spec.find(i) == spec.end())
  1961. throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i);
  1962. } else {
  1963. if (spec.find(i) != spec.end())
  1964. throw BuildError(format("output (`%1%') is not allowed to refer to path `%2%'") % actualPath % i);
  1965. }
  1966. };
  1967. checkRefs("allowedReferences", true, false);
  1968. checkRefs("allowedRequisites", true, true);
  1969. checkRefs("disallowedReferences", false, false);
  1970. checkRefs("disallowedRequisites", false, true);
  1971. if (curRound == nrRounds) {
  1972. worker.store.optimisePath(path); // FIXME: combine with scanForReferences()
  1973. worker.store.markContentsGood(path);
  1974. }
  1975. ValidPathInfo info;
  1976. info.path = path;
  1977. info.hash = hash.first;
  1978. info.narSize = hash.second;
  1979. info.references = references;
  1980. info.deriver = drvPath;
  1981. infos.push_back(info);
  1982. }
  1983. /* Compare the result with the previous round, and report which
  1984. path is different, if any.*/
  1985. if (curRound > 1 && prevInfos != infos) {
  1986. assert(prevInfos.size() == infos.size());
  1987. for (auto i = prevInfos.begin(), j = infos.begin(); i != prevInfos.end(); ++i, ++j)
  1988. if (!(*i == *j)) {
  1989. Path prev = i->path + checkSuffix;
  1990. if (pathExists(prev))
  1991. throw NotDeterministic(
  1992. format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round")
  1993. % i->path % drvPath % prev);
  1994. else
  1995. throw NotDeterministic(
  1996. format("output ‘%1%’ of ‘%2%’ differs from previous round")
  1997. % i->path % drvPath);
  1998. }
  1999. assert(false); // shouldn't happen
  2000. }
  2001. if (settings.keepFailed) {
  2002. for (auto & i : drv.outputs) {
  2003. Path prev = i.second.path + checkSuffix;
  2004. if (pathExists(prev)) deletePath(prev);
  2005. if (curRound < nrRounds) {
  2006. Path dst = i.second.path + checkSuffix;
  2007. if (rename(i.second.path.c_str(), dst.c_str()))
  2008. throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst);
  2009. }
  2010. }
  2011. }
  2012. if (curRound < nrRounds) {
  2013. prevInfos = infos;
  2014. return;
  2015. }
  2016. /* Register each output path as valid, and register the sets of
  2017. paths referenced by each of them. If there are cycles in the
  2018. outputs, this will fail. */
  2019. worker.store.registerValidPaths(infos);
  2020. }
  2021. string drvsLogDir = "drvs";
  2022. Path DerivationGoal::openLogFile()
  2023. {
  2024. logSize = 0;
  2025. if (!settings.keepLog) return "";
  2026. string baseName = baseNameOf(drvPath);
  2027. /* Create a log file. */
  2028. Path dir = (format("%1%/%2%/%3%/") % settings.nixLogDir % drvsLogDir % string(baseName, 0, 2)).str();
  2029. createDirs(dir);
  2030. switch (settings.logCompression)
  2031. {
  2032. case COMPRESSION_GZIP: {
  2033. Path logFileName = (format("%1%/%2%.gz") % dir % string(baseName, 2)).str();
  2034. AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
  2035. if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName);
  2036. closeOnExec(fd);
  2037. /* Note: FD will be closed by 'gzclose'. */
  2038. if (!(gzLogFile = gzdopen(fd.borrow(), "w")))
  2039. throw Error(format("cannot open compressed log file `%1%'") % logFileName);
  2040. gzbuffer(gzLogFile, 32768);
  2041. gzsetparams(gzLogFile, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY);
  2042. return logFileName;
  2043. }
  2044. #if HAVE_BZLIB_H
  2045. case COMPRESSION_BZIP2: {
  2046. Path logFileName = (format("%1%/%2%.bz2") % dir % string(baseName, 2)).str();
  2047. AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
  2048. if (fd == -1) throw SysError(format("creating log file `%1%'") % logFileName);
  2049. closeOnExec(fd);
  2050. if (!(fLogFile = fdopen(fd.borrow(), "w")))
  2051. throw SysError(format("opening file `%1%'") % logFileName);
  2052. int err;
  2053. if (!(bzLogFile = BZ2_bzWriteOpen(&err, fLogFile, 9, 0, 0)))
  2054. throw Error(format("cannot open compressed log file `%1%'") % logFileName);
  2055. return logFileName;
  2056. }
  2057. #endif
  2058. case COMPRESSION_NONE: {
  2059. Path logFileName = (format("%1%/%2%") % dir % string(baseName, 2)).str();
  2060. fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
  2061. if (fdLogFile == -1) throw SysError(format("creating log file `%1%'") % logFileName);
  2062. closeOnExec(fdLogFile);
  2063. return logFileName;
  2064. }
  2065. }
  2066. abort();
  2067. }
  2068. void DerivationGoal::closeLogFile()
  2069. {
  2070. if (gzLogFile) {
  2071. int err;
  2072. err = gzclose(gzLogFile);
  2073. gzLogFile = NULL;
  2074. if (err != Z_OK) throw Error(format("cannot close compressed log file (gzip error = %1%)") % err);
  2075. }
  2076. #if HAVE_BZLIB_H
  2077. else if (bzLogFile) {
  2078. int err;
  2079. BZ2_bzWriteClose(&err, bzLogFile, 0, 0, 0);
  2080. bzLogFile = 0;
  2081. if (err != BZ_OK) throw Error(format("cannot close compressed log file (BZip2 error = %1%)") % err);
  2082. }
  2083. #endif
  2084. if (fLogFile) {
  2085. fclose(fLogFile);
  2086. fLogFile = 0;
  2087. }
  2088. fdLogFile.close();
  2089. }
  2090. static void _chown(const Path & path, uid_t uid, gid_t gid)
  2091. {
  2092. checkInterrupt();
  2093. if (lchown(path.c_str(), uid, gid) == -1) {
  2094. throw SysError(format("change owner and group of `%1%'") % path);
  2095. }
  2096. struct stat st = lstat(path);
  2097. if (S_ISDIR(st.st_mode)) {
  2098. for (auto & i : readDirectory(path))
  2099. _chown(path + "/" + i.name, uid, gid);
  2100. }
  2101. }
  2102. void DerivationGoal::deleteTmpDir(bool force)
  2103. {
  2104. if (tmpDir != "") {
  2105. // When useChroot is true, tmpDir looks like
  2106. // "/tmp/guix-build-foo.drv-0/top". Its parent is root-owned.
  2107. string top;
  2108. if (useChroot) {
  2109. if (baseNameOf(tmpDir) != "top") abort();
  2110. top = dirOf(tmpDir);
  2111. } else top = tmpDir;
  2112. if (settings.keepFailed && !force) {
  2113. printMsg(lvlError,
  2114. format("note: keeping build directory `%2%'")
  2115. % drvPath % top);
  2116. chmod(tmpDir.c_str(), 0755);
  2117. // Change the ownership if clientUid is set. Never change the
  2118. // ownership or the group to "root" for security reasons.
  2119. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) {
  2120. _chown(tmpDir, settings.clientUid,
  2121. settings.clientGid != 0 ? settings.clientGid : -1);
  2122. if (top != tmpDir) {
  2123. // Rename tmpDir to its parent, with an intermediate step.
  2124. string pivot = top + ".pivot";
  2125. if (rename(top.c_str(), pivot.c_str()) == -1)
  2126. throw SysError("pivoting failed build tree");
  2127. if (rename((pivot + "/top").c_str(), top.c_str()) == -1)
  2128. throw SysError("renaming failed build tree");
  2129. rmdir(pivot.c_str());
  2130. }
  2131. }
  2132. }
  2133. else {
  2134. deletePath(tmpDir);
  2135. if (top != tmpDir) rmdir(dirOf(tmpDir).c_str());
  2136. }
  2137. tmpDir = "";
  2138. }
  2139. }
  2140. void DerivationGoal::handleChildOutput(int fd, const string & data)
  2141. {
  2142. string prefix;
  2143. if (settings.multiplexedBuildOutput) {
  2144. /* Print a prefix that allows clients to determine whether a message
  2145. comes from the daemon or from a build process, and in the latter
  2146. case, which build process it comes from. The PID here matches the
  2147. one given in "@ build-started" traces; it's shorter that the
  2148. derivation file name, hence this choice. */
  2149. prefix = "@ build-log "
  2150. + std::to_string(pid < 0 ? hook->pid : pid)
  2151. + " " + std::to_string(data.size()) + "\n";
  2152. }
  2153. if ((hook && fd == hook->builderOut.readSide) ||
  2154. (!hook && fd == builderOut.readSide))
  2155. {
  2156. logSize += data.size();
  2157. if (settings.maxLogSize && logSize > settings.maxLogSize) {
  2158. printMsg(lvlError,
  2159. format("%1% killed after writing more than %2% bytes of log output")
  2160. % getName() % settings.maxLogSize);
  2161. timedOut(); // not really a timeout, but close enough
  2162. return;
  2163. }
  2164. if (verbosity >= settings.buildVerbosity)
  2165. writeToStderr(prefix + data);
  2166. if (gzLogFile) {
  2167. if (data.size() > 0) {
  2168. int count, err;
  2169. count = gzwrite(gzLogFile, data.data(), data.size());
  2170. if (count == 0) throw Error(format("cannot write to compressed log file (gzip error = %1%)") % gzerror(gzLogFile, &err));
  2171. }
  2172. #if HAVE_BZLIB_H
  2173. } else if (bzLogFile) {
  2174. int err;
  2175. BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size());
  2176. if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err);
  2177. #endif
  2178. } else if (fdLogFile != -1)
  2179. writeFull(fdLogFile, data);
  2180. }
  2181. if (hook && fd == hook->fromAgent.readSide)
  2182. writeToStderr(prefix + data);
  2183. }
  2184. void DerivationGoal::handleEOF(int fd)
  2185. {
  2186. worker.wakeUp(shared_from_this());
  2187. }
  2188. PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
  2189. {
  2190. PathSet result;
  2191. foreach (DerivationOutputs::iterator, i, drv.outputs) {
  2192. if (!wantOutput(i->first, wantedOutputs)) continue;
  2193. bool good =
  2194. worker.store.isValidPath(i->second.path) &&
  2195. (!checkHash || worker.store.pathContentsGood(i->second.path));
  2196. if (good == returnValid) result.insert(i->second.path);
  2197. }
  2198. return result;
  2199. }
  2200. bool DerivationGoal::pathFailed(const Path & path)
  2201. {
  2202. if (!settings.cacheFailure) return false;
  2203. if (!worker.store.hasPathFailed(path)) return false;
  2204. printMsg(lvlError, format("builder for `%1%' failed previously (cached)") % path);
  2205. if (settings.printBuildTrace)
  2206. printMsg(lvlError, format("@ build-failed %1% - cached") % drvPath);
  2207. done(BuildResult::CachedFailure);
  2208. return true;
  2209. }
  2210. Path DerivationGoal::addHashRewrite(const Path & path)
  2211. {
  2212. string h1 = string(path, settings.nixStore.size() + 1, 32);
  2213. string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32);
  2214. Path p = settings.nixStore + "/" + h2 + string(path, settings.nixStore.size() + 33);
  2215. if (pathExists(p)) deletePath(p);
  2216. assert(path.size() == p.size());
  2217. rewritesToTmp[h1] = h2;
  2218. rewritesFromTmp[h2] = h1;
  2219. redirectedOutputs[path] = p;
  2220. printMsg(lvlChatty, format("output '%1%' redirected to '%2%'")
  2221. % path % p);
  2222. return p;
  2223. }
  2224. void DerivationGoal::done(BuildResult::Status status, const string & msg)
  2225. {
  2226. result.status = status;
  2227. result.errorMsg = msg;
  2228. amDone(result.success() ? ecSuccess : ecFailed);
  2229. if (result.status == BuildResult::TimedOut)
  2230. worker.timedOut = true;
  2231. if (result.status == BuildResult::PermanentFailure || result.status == BuildResult::CachedFailure)
  2232. worker.permanentFailure = true;
  2233. }
  2234. //////////////////////////////////////////////////////////////////////
  2235. class SubstitutionGoal : public Goal
  2236. {
  2237. friend class Worker;
  2238. private:
  2239. /* The store path that should be realised through a substitute. */
  2240. Path storePath;
  2241. /* Path info returned by the substituter's query info operation. */
  2242. SubstitutablePathInfo info;
  2243. /* Lock on the store path. */
  2244. std::shared_ptr<PathLocks> outputLock;
  2245. /* Whether to try to repair a valid path. */
  2246. bool repair;
  2247. /* Location where we're downloading the substitute. Differs from
  2248. storePath when doing a repair. */
  2249. Path destPath;
  2250. typedef void (SubstitutionGoal::*GoalState)();
  2251. GoalState state;
  2252. /* The substituter. */
  2253. std::shared_ptr<Agent> substituter;
  2254. /* Either the empty string, or the status phrase returned by the
  2255. substituter. */
  2256. string status;
  2257. void tryNext();
  2258. public:
  2259. SubstitutionGoal(const Path & storePath, Worker & worker, bool repair = false);
  2260. ~SubstitutionGoal();
  2261. void timedOut();
  2262. string key()
  2263. {
  2264. /* "a$" ensures substitution goals happen before derivation
  2265. goals. */
  2266. return "a$" + storePathToName(storePath) + "$" + storePath;
  2267. }
  2268. void work();
  2269. /* The states. */
  2270. void init();
  2271. void gotInfo();
  2272. void referencesValid();
  2273. void tryToRun();
  2274. void finished();
  2275. /* Callback used by the worker to write to the log. */
  2276. void handleChildOutput(int fd, const string & data);
  2277. void handleEOF(int fd);
  2278. Path getStorePath() { return storePath; }
  2279. };
  2280. SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool repair)
  2281. : Goal(worker)
  2282. , repair(repair)
  2283. {
  2284. this->storePath = storePath;
  2285. state = &SubstitutionGoal::init;
  2286. name = (format("substitution of `%1%'") % storePath).str();
  2287. trace("created");
  2288. }
  2289. SubstitutionGoal::~SubstitutionGoal()
  2290. {
  2291. if (substituter) worker.childTerminated(substituter->pid);
  2292. }
  2293. void SubstitutionGoal::timedOut()
  2294. {
  2295. if (settings.printBuildTrace)
  2296. printMsg(lvlError, format("@ substituter-failed %1% timeout") % storePath);
  2297. if (substituter) {
  2298. pid_t savedPid = substituter->pid;
  2299. substituter.reset();
  2300. worker.childTerminated(savedPid);
  2301. }
  2302. amDone(ecFailed);
  2303. }
  2304. void SubstitutionGoal::work()
  2305. {
  2306. (this->*state)();
  2307. }
  2308. void SubstitutionGoal::init()
  2309. {
  2310. trace("init");
  2311. worker.store.addTempRoot(storePath);
  2312. /* If the path already exists we're done. */
  2313. if (!repair && worker.store.isValidPath(storePath)) {
  2314. amDone(ecSuccess);
  2315. return;
  2316. }
  2317. if (settings.readOnlyMode)
  2318. throw Error(format("cannot substitute path `%1%' - no write access to the store") % storePath);
  2319. tryNext();
  2320. }
  2321. void SubstitutionGoal::tryNext()
  2322. {
  2323. trace("trying substituter");
  2324. SubstitutablePathInfos infos;
  2325. PathSet dummy(singleton<PathSet>(storePath));
  2326. worker.store.querySubstitutablePathInfos(dummy, infos);
  2327. SubstitutablePathInfos::iterator k = infos.find(storePath);
  2328. if (k == infos.end()) {
  2329. /* None left. Terminate this goal and let someone else deal
  2330. with it. */
  2331. debug(format("path `%1%' is required, but there is no substituter that can build it") % storePath);
  2332. /* Hack: don't indicate failure if there were no substituters.
  2333. In that case the calling derivation should just do a
  2334. build. */
  2335. amDone(ecNoSubstituters);
  2336. return;
  2337. }
  2338. /* Found a substitute. */
  2339. info = k->second;
  2340. /* To maintain the closure invariant, we first have to realise the
  2341. paths referenced by this one. */
  2342. foreach (PathSet::iterator, i, info.references)
  2343. if (*i != storePath) /* ignore self-references */
  2344. addWaitee(worker.makeSubstitutionGoal(*i));
  2345. if (waitees.empty()) /* to prevent hang (no wake-up event) */
  2346. referencesValid();
  2347. else
  2348. state = &SubstitutionGoal::referencesValid;
  2349. }
  2350. void SubstitutionGoal::referencesValid()
  2351. {
  2352. trace("all references realised");
  2353. if (nrFailed > 0) {
  2354. debug(format("some references of path `%1%' could not be realised") % storePath);
  2355. amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed);
  2356. return;
  2357. }
  2358. foreach (PathSet::iterator, i, info.references)
  2359. if (*i != storePath) /* ignore self-references */
  2360. assert(worker.store.isValidPath(*i));
  2361. state = &SubstitutionGoal::tryToRun;
  2362. worker.wakeUp(shared_from_this());
  2363. }
  2364. void SubstitutionGoal::tryToRun()
  2365. {
  2366. trace("trying to run");
  2367. /* Make sure that we are allowed to start a build. Note that even
  2368. is maxBuildJobs == 0 (no local builds allowed), we still allow
  2369. a substituter to run. This is because substitutions cannot be
  2370. distributed to another machine via the build hook. */
  2371. if (worker.getNrLocalBuilds() >= (settings.maxBuildJobs == 0 ? 1 : settings.maxBuildJobs)) {
  2372. worker.waitForBuildSlot(shared_from_this());
  2373. return;
  2374. }
  2375. /* Maybe a derivation goal has already locked this path
  2376. (exceedingly unlikely, since it should have used a substitute
  2377. first, but let's be defensive). */
  2378. outputLock.reset(); // make sure this goal's lock is gone
  2379. if (pathIsLockedByMe(storePath)) {
  2380. debug(format("restarting substitution of `%1%' because it's locked by another goal")
  2381. % storePath);
  2382. worker.waitForAnyGoal(shared_from_this());
  2383. return; /* restart in the tryToRun() state when another goal finishes */
  2384. }
  2385. /* Acquire a lock on the output path. */
  2386. outputLock = std::shared_ptr<PathLocks>(new PathLocks);
  2387. if (!outputLock->lockPaths(singleton<PathSet>(storePath), "", false)) {
  2388. worker.waitForAWhile(shared_from_this());
  2389. return;
  2390. }
  2391. /* Check again whether the path is invalid. */
  2392. if (!repair && worker.store.isValidPath(storePath)) {
  2393. debug(format("store path `%1%' has become valid") % storePath);
  2394. outputLock->setDeletion(true);
  2395. amDone(ecSuccess);
  2396. return;
  2397. }
  2398. printMsg(lvlInfo, format("fetching path `%1%'...") % storePath);
  2399. destPath = repair ? storePath + ".tmp" : storePath;
  2400. /* Remove the (stale) output path if it exists. */
  2401. if (pathExists(destPath))
  2402. deletePath(destPath);
  2403. if (!worker.substituter) {
  2404. const Strings args = { "substitute", "--substitute" };
  2405. const std::map<string, string> env = {
  2406. { "_NIX_OPTIONS",
  2407. settings.pack() + "deduplicate="
  2408. + (settings.autoOptimiseStore ? "yes" : "no")
  2409. }
  2410. };
  2411. worker.substituter = std::make_shared<Agent>(settings.guixProgram, args, env);
  2412. }
  2413. /* Borrow the worker's substituter. */
  2414. if (!substituter) substituter.swap(worker.substituter);
  2415. /* Send the request to the substituter. */
  2416. writeLine(substituter->toAgent.writeSide,
  2417. (format("substitute %1% %2%") % storePath % destPath).str());
  2418. set<int> fds;
  2419. fds.insert(substituter->fromAgent.readSide);
  2420. fds.insert(substituter->builderOut.readSide);
  2421. worker.childStarted(shared_from_this(), substituter->pid, fds, true, true);
  2422. state = &SubstitutionGoal::finished;
  2423. if (settings.printBuildTrace)
  2424. /* The second element in the message used to be the name of the
  2425. substituter but we're left with only one. */
  2426. printMsg(lvlError, format("@ substituter-started %1% substitute") % storePath);
  2427. }
  2428. void SubstitutionGoal::finished()
  2429. {
  2430. trace("substitute finished");
  2431. /* Remove the 'guix substitute' process from the list of children. */
  2432. worker.childTerminated(substituter->pid);
  2433. /* If max-jobs > 1, the worker might have created a new 'substitute'
  2434. process in the meantime. If that is the case, terminate ours;
  2435. otherwise, give it back to the worker. */
  2436. if (worker.substituter) {
  2437. substituter.reset ();
  2438. } else {
  2439. worker.substituter.swap(substituter);
  2440. }
  2441. /* Check the exit status and the build result. */
  2442. HashResult hash;
  2443. try {
  2444. auto statusList = tokenizeString<vector<string> >(status);
  2445. if (statusList.empty()) {
  2446. throw SubstError(format("fetching path `%1%' (empty status: '%2%')")
  2447. % storePath % status);
  2448. } else if (statusList[0] == "hash-mismatch") {
  2449. if (settings.printBuildTrace) {
  2450. auto hashType = statusList[1];
  2451. auto expectedHash = statusList[2];
  2452. auto actualHash = statusList[3];
  2453. printMsg(lvlError, format("@ hash-mismatch %1% %2% %3% %4%")
  2454. % storePath
  2455. % hashType % expectedHash % actualHash);
  2456. }
  2457. throw SubstError(format("hash mismatch for substituted item `%1%'") % storePath);
  2458. } else if (statusList[0] == "success") {
  2459. if (!pathExists(destPath))
  2460. throw SubstError(format("substitute did not produce path `%1%'") % destPath);
  2461. std::string hashStr = statusList[1];
  2462. size_t n = hashStr.find(':');
  2463. if (n == string::npos)
  2464. throw Error(format("bad hash from substituter: %1%") % hashStr);
  2465. HashType hashType = parseHashType(string(hashStr, 0, n));
  2466. switch (hashType) {
  2467. case htUnknown:
  2468. throw Error(format("unknown hash algorithm in `%1%'") % hashStr);
  2469. case htSHA256:
  2470. hash.first = parseHash16or32(hashType, string(hashStr, n + 1));
  2471. hash.second = std::atoi(statusList[2].c_str());
  2472. break;
  2473. default:
  2474. /* The database only stores SHA256 hashes, so compute it. */
  2475. hash = hashPath(htSHA256, destPath);
  2476. break;
  2477. }
  2478. }
  2479. else
  2480. throw SubstError(format("fetching path `%1%' (status: '%2%')")
  2481. % storePath % status);
  2482. } catch (SubstError & e) {
  2483. printMsg(lvlInfo, e.msg());
  2484. if (settings.printBuildTrace) {
  2485. printMsg(lvlError, format("@ substituter-failed %1% %2% %3%")
  2486. % storePath % status % e.msg());
  2487. }
  2488. amDone(ecFailed);
  2489. return;
  2490. }
  2491. if (repair) replaceValidPath(storePath, destPath);
  2492. /* Note: 'guix substitute' takes care of resetting timestamps and of
  2493. deduplicating 'destPath', so no need to do it here. */
  2494. ValidPathInfo info2;
  2495. info2.path = storePath;
  2496. info2.hash = hash.first;
  2497. info2.narSize = hash.second;
  2498. info2.references = info.references;
  2499. info2.deriver = info.deriver;
  2500. worker.store.registerValidPath(info2);
  2501. outputLock->setDeletion(true);
  2502. outputLock.reset();
  2503. worker.store.markContentsGood(storePath);
  2504. printMsg(lvlChatty,
  2505. format("substitution of path `%1%' succeeded") % storePath);
  2506. if (settings.printBuildTrace)
  2507. printMsg(lvlError, format("@ substituter-succeeded %1%") % storePath);
  2508. amDone(ecSuccess);
  2509. }
  2510. void SubstitutionGoal::handleChildOutput(int fd, const string & data)
  2511. {
  2512. if (verbosity >= settings.buildVerbosity
  2513. && fd == substituter->fromAgent.readSide) {
  2514. writeToStderr(data);
  2515. /* Don't write substitution output to a log file for now. We
  2516. probably should, though. */
  2517. }
  2518. if (fd == substituter->builderOut.readSide) {
  2519. /* DATA may consist of several lines. Process them one by one. */
  2520. string input = data;
  2521. while (!input.empty()) {
  2522. /* Process up to the first newline. */
  2523. size_t end = input.find_first_of("\n");
  2524. string trimmed = (end != string::npos) ? input.substr(0, end) : input;
  2525. /* Update the goal's state accordingly. */
  2526. if (status == "") {
  2527. status = trimmed;
  2528. worker.wakeUp(shared_from_this());
  2529. } else {
  2530. printMsg(lvlError, format("unexpected substituter message '%1%'") % input);
  2531. }
  2532. input = (end != string::npos) ? input.substr(end + 1) : "";
  2533. }
  2534. }
  2535. }
  2536. void SubstitutionGoal::handleEOF(int fd)
  2537. {
  2538. worker.wakeUp(shared_from_this());
  2539. }
  2540. //////////////////////////////////////////////////////////////////////
  2541. static bool working = false;
  2542. Worker::Worker(LocalStore & store)
  2543. : store(store)
  2544. {
  2545. /* Debugging: prevent recursive workers. */
  2546. if (working) abort();
  2547. working = true;
  2548. nrLocalBuilds = 0;
  2549. lastWokenUp = 0;
  2550. permanentFailure = false;
  2551. timedOut = false;
  2552. }
  2553. Worker::~Worker()
  2554. {
  2555. working = false;
  2556. /* Explicitly get rid of all strong pointers now. After this all
  2557. goals that refer to this worker should be gone. (Otherwise we
  2558. are in trouble, since goals may call childTerminated() etc. in
  2559. their destructors). */
  2560. topGoals.clear();
  2561. }
  2562. GoalPtr Worker::makeDerivationGoal(const Path & path,
  2563. const StringSet & wantedOutputs, BuildMode buildMode)
  2564. {
  2565. GoalPtr goal = derivationGoals[path].lock();
  2566. if (!goal) {
  2567. goal = GoalPtr(new DerivationGoal(path, wantedOutputs, *this, buildMode));
  2568. derivationGoals[path] = goal;
  2569. wakeUp(goal);
  2570. } else
  2571. (dynamic_cast<DerivationGoal *>(goal.get()))->addWantedOutputs(wantedOutputs);
  2572. return goal;
  2573. }
  2574. GoalPtr Worker::makeSubstitutionGoal(const Path & path, bool repair)
  2575. {
  2576. GoalPtr goal = substitutionGoals[path].lock();
  2577. if (!goal) {
  2578. goal = GoalPtr(new SubstitutionGoal(path, *this, repair));
  2579. substitutionGoals[path] = goal;
  2580. wakeUp(goal);
  2581. }
  2582. return goal;
  2583. }
  2584. static void removeGoal(GoalPtr goal, WeakGoalMap & goalMap)
  2585. {
  2586. /* !!! inefficient */
  2587. for (WeakGoalMap::iterator i = goalMap.begin();
  2588. i != goalMap.end(); )
  2589. if (i->second.lock() == goal) {
  2590. WeakGoalMap::iterator j = i; ++j;
  2591. goalMap.erase(i);
  2592. i = j;
  2593. }
  2594. else ++i;
  2595. }
  2596. void Worker::removeGoal(GoalPtr goal)
  2597. {
  2598. nix::removeGoal(goal, derivationGoals);
  2599. nix::removeGoal(goal, substitutionGoals);
  2600. if (topGoals.find(goal) != topGoals.end()) {
  2601. topGoals.erase(goal);
  2602. /* If a top-level goal failed, then kill all other goals
  2603. (unless keepGoing was set). */
  2604. if (goal->getExitCode() == Goal::ecFailed && !settings.keepGoing)
  2605. topGoals.clear();
  2606. }
  2607. /* Wake up goals waiting for any goal to finish. */
  2608. foreach (WeakGoals::iterator, i, waitingForAnyGoal) {
  2609. GoalPtr goal = i->lock();
  2610. if (goal) wakeUp(goal);
  2611. }
  2612. waitingForAnyGoal.clear();
  2613. }
  2614. void Worker::wakeUp(GoalPtr goal)
  2615. {
  2616. goal->trace("woken up");
  2617. addToWeakGoals(awake, goal);
  2618. }
  2619. unsigned Worker::getNrLocalBuilds()
  2620. {
  2621. return nrLocalBuilds;
  2622. }
  2623. void Worker::childStarted(GoalPtr goal,
  2624. pid_t pid, const set<int> & fds, bool inBuildSlot,
  2625. bool respectTimeouts)
  2626. {
  2627. Child child;
  2628. child.goal = goal;
  2629. child.fds = fds;
  2630. child.timeStarted = child.lastOutput = time(0);
  2631. child.inBuildSlot = inBuildSlot;
  2632. child.respectTimeouts = respectTimeouts;
  2633. children[pid] = child;
  2634. if (inBuildSlot) nrLocalBuilds++;
  2635. }
  2636. void Worker::childTerminated(pid_t pid, bool wakeSleepers)
  2637. {
  2638. assert(pid != -1); /* common mistake */
  2639. Children::iterator i = children.find(pid);
  2640. assert(i != children.end());
  2641. if (i->second.inBuildSlot) {
  2642. assert(nrLocalBuilds > 0);
  2643. nrLocalBuilds--;
  2644. }
  2645. children.erase(pid);
  2646. if (wakeSleepers) {
  2647. /* Wake up goals waiting for a build slot. */
  2648. foreach (WeakGoals::iterator, i, wantingToBuild) {
  2649. GoalPtr goal = i->lock();
  2650. if (goal) wakeUp(goal);
  2651. }
  2652. wantingToBuild.clear();
  2653. }
  2654. }
  2655. void Worker::waitForBuildSlot(GoalPtr goal)
  2656. {
  2657. debug("wait for build slot");
  2658. if (getNrLocalBuilds() < settings.maxBuildJobs)
  2659. wakeUp(goal); /* we can do it right away */
  2660. else
  2661. addToWeakGoals(wantingToBuild, goal);
  2662. }
  2663. void Worker::waitForAnyGoal(GoalPtr goal)
  2664. {
  2665. debug("wait for any goal");
  2666. addToWeakGoals(waitingForAnyGoal, goal);
  2667. }
  2668. void Worker::waitForAWhile(GoalPtr goal)
  2669. {
  2670. debug("wait for a while");
  2671. addToWeakGoals(waitingForAWhile, goal);
  2672. }
  2673. void Worker::run(const Goals & _topGoals)
  2674. {
  2675. foreach (Goals::iterator, i, _topGoals) topGoals.insert(*i);
  2676. startNest(nest, lvlDebug, format("entered goal loop"));
  2677. while (1) {
  2678. checkInterrupt();
  2679. /* Call every wake goal (in the ordering established by
  2680. CompareGoalPtrs). */
  2681. while (!awake.empty() && !topGoals.empty()) {
  2682. Goals awake2;
  2683. for (auto & i : awake) {
  2684. GoalPtr goal = i.lock();
  2685. if (goal) awake2.insert(goal);
  2686. }
  2687. awake.clear();
  2688. for (auto & goal : awake2) {
  2689. checkInterrupt();
  2690. goal->work();
  2691. if (topGoals.empty()) break; // stuff may have been cancelled
  2692. }
  2693. }
  2694. if (topGoals.empty()) break;
  2695. /* Wait for input. */
  2696. if (!children.empty() || !waitingForAWhile.empty())
  2697. waitForInput();
  2698. else {
  2699. if (awake.empty() && settings.maxBuildJobs == 0) throw Error(
  2700. "unable to start any build; either increase `--max-jobs' "
  2701. "or enable distributed builds");
  2702. assert(!awake.empty());
  2703. }
  2704. }
  2705. /* If --keep-going is not set, it's possible that the main goal
  2706. exited while some of its subgoals were still active. But if
  2707. --keep-going *is* set, then they must all be finished now. */
  2708. assert(!settings.keepGoing || awake.empty());
  2709. assert(!settings.keepGoing || wantingToBuild.empty());
  2710. assert(!settings.keepGoing || children.empty());
  2711. }
  2712. void Worker::waitForInput()
  2713. {
  2714. printMsg(lvlVomit, "waiting for children");
  2715. /* Process output from the file descriptors attached to the
  2716. children, namely log output and output path creation commands.
  2717. We also use this to detect child termination: if we get EOF on
  2718. the logger pipe of a build, we assume that the builder has
  2719. terminated. */
  2720. bool useTimeout = false;
  2721. struct timeval timeout;
  2722. timeout.tv_usec = 0;
  2723. time_t before = time(0);
  2724. /* If we're monitoring for silence on stdout/stderr, or if there
  2725. is a build timeout, then wait for input until the first
  2726. deadline for any child. */
  2727. assert(sizeof(time_t) >= sizeof(long));
  2728. time_t nearest = LONG_MAX; // nearest deadline
  2729. foreach (Children::iterator, i, children) {
  2730. if (!i->second.respectTimeouts) continue;
  2731. if (settings.maxSilentTime != 0)
  2732. nearest = std::min(nearest, i->second.lastOutput + settings.maxSilentTime);
  2733. if (settings.buildTimeout != 0)
  2734. nearest = std::min(nearest, i->second.timeStarted + settings.buildTimeout);
  2735. }
  2736. if (nearest != LONG_MAX) {
  2737. timeout.tv_sec = std::max((time_t) 1, nearest - before);
  2738. useTimeout = true;
  2739. printMsg(lvlVomit, format("sleeping %1% seconds") % timeout.tv_sec);
  2740. }
  2741. /* If we are polling goals that are waiting for a lock, then wake
  2742. up after a few seconds at most. */
  2743. if (!waitingForAWhile.empty()) {
  2744. useTimeout = true;
  2745. if (lastWokenUp == 0)
  2746. printMsg(lvlError, "waiting for locks or build slots...");
  2747. if (lastWokenUp == 0 || lastWokenUp > before) lastWokenUp = before;
  2748. timeout.tv_sec = std::max((time_t) 1, (time_t) (lastWokenUp + settings.pollInterval - before));
  2749. } else lastWokenUp = 0;
  2750. using namespace std;
  2751. /* Use select() to wait for the input side of any logger pipe to
  2752. become `available'. Note that `available' (i.e., non-blocking)
  2753. includes EOF. */
  2754. fd_set fds;
  2755. FD_ZERO(&fds);
  2756. int fdMax = 0;
  2757. foreach (Children::iterator, i, children) {
  2758. foreach (set<int>::iterator, j, i->second.fds) {
  2759. FD_SET(*j, &fds);
  2760. if (*j >= fdMax) fdMax = *j + 1;
  2761. }
  2762. }
  2763. if (select(fdMax, &fds, 0, 0, useTimeout ? &timeout : 0) == -1) {
  2764. if (errno == EINTR) return;
  2765. throw SysError("waiting for input");
  2766. }
  2767. time_t after = time(0);
  2768. /* Process all available file descriptors. */
  2769. /* Since goals may be canceled from inside the loop below (causing
  2770. them go be erased from the `children' map), we have to be
  2771. careful that we don't keep iterators alive across calls to
  2772. timedOut(). */
  2773. set<pid_t> pids;
  2774. foreach (Children::iterator, i, children) pids.insert(i->first);
  2775. foreach (set<pid_t>::iterator, i, pids) {
  2776. checkInterrupt();
  2777. Children::iterator j = children.find(*i);
  2778. if (j == children.end()) continue; // child destroyed
  2779. GoalPtr goal = j->second.goal.lock();
  2780. assert(goal);
  2781. set<int> fds2(j->second.fds);
  2782. foreach (set<int>::iterator, k, fds2) {
  2783. if (FD_ISSET(*k, &fds)) {
  2784. unsigned char buffer[4096];
  2785. ssize_t rd = read(*k, buffer, sizeof(buffer));
  2786. if (rd == -1) {
  2787. if (errno != EINTR)
  2788. throw SysError(format("reading from %1%")
  2789. % goal->getName());
  2790. } else if (rd == 0) {
  2791. debug(format("%1%: got EOF") % goal->getName());
  2792. goal->handleEOF(*k);
  2793. j->second.fds.erase(*k);
  2794. } else {
  2795. printMsg(lvlVomit, format("%1%: read %2% bytes")
  2796. % goal->getName() % rd);
  2797. string data((char *) buffer, rd);
  2798. j->second.lastOutput = after;
  2799. goal->handleChildOutput(*k, data);
  2800. }
  2801. }
  2802. }
  2803. if (goal->getExitCode() == Goal::ecBusy &&
  2804. settings.maxSilentTime != 0 &&
  2805. j->second.respectTimeouts &&
  2806. after - j->second.lastOutput >= (time_t) settings.maxSilentTime)
  2807. {
  2808. printMsg(lvlError,
  2809. format("%1% timed out after %2% seconds of silence")
  2810. % goal->getName() % settings.maxSilentTime);
  2811. goal->timedOut();
  2812. }
  2813. else if (goal->getExitCode() == Goal::ecBusy &&
  2814. settings.buildTimeout != 0 &&
  2815. j->second.respectTimeouts &&
  2816. after - j->second.timeStarted >= (time_t) settings.buildTimeout)
  2817. {
  2818. printMsg(lvlError,
  2819. format("%1% timed out after %2% seconds")
  2820. % goal->getName() % settings.buildTimeout);
  2821. goal->timedOut();
  2822. }
  2823. }
  2824. if (!waitingForAWhile.empty() && lastWokenUp + settings.pollInterval <= after) {
  2825. lastWokenUp = after;
  2826. foreach (WeakGoals::iterator, i, waitingForAWhile) {
  2827. GoalPtr goal = i->lock();
  2828. if (goal) wakeUp(goal);
  2829. }
  2830. waitingForAWhile.clear();
  2831. }
  2832. }
  2833. unsigned int Worker::exitStatus()
  2834. {
  2835. return timedOut ? 101 : (permanentFailure ? 100 : 1);
  2836. }
  2837. //////////////////////////////////////////////////////////////////////
  2838. void LocalStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
  2839. {
  2840. startNest(nest, lvlDebug,
  2841. format("building %1%") % showPaths(drvPaths));
  2842. Worker worker(*this);
  2843. Goals goals;
  2844. foreach (PathSet::const_iterator, i, drvPaths) {
  2845. DrvPathWithOutputs i2 = parseDrvPathWithOutputs(*i);
  2846. if (isDerivation(i2.first))
  2847. goals.insert(worker.makeDerivationGoal(i2.first, i2.second, buildMode));
  2848. else
  2849. goals.insert(worker.makeSubstitutionGoal(*i, buildMode));
  2850. }
  2851. worker.run(goals);
  2852. PathSet failed;
  2853. foreach (Goals::iterator, i, goals)
  2854. if ((*i)->getExitCode() == Goal::ecFailed) {
  2855. DerivationGoal * i2 = dynamic_cast<DerivationGoal *>(i->get());
  2856. if (i2) failed.insert(i2->getDrvPath());
  2857. else failed.insert(dynamic_cast<SubstitutionGoal *>(i->get())->getStorePath());
  2858. }
  2859. if (!failed.empty())
  2860. throw Error(format("build of %1% failed") % showPaths(failed), worker.exitStatus());
  2861. }
  2862. void LocalStore::ensurePath(const Path & path)
  2863. {
  2864. /* If the path is already valid, we're done. */
  2865. if (isValidPath(path)) return;
  2866. Worker worker(*this);
  2867. GoalPtr goal = worker.makeSubstitutionGoal(path);
  2868. Goals goals = singleton<Goals>(goal);
  2869. worker.run(goals);
  2870. if (goal->getExitCode() != Goal::ecSuccess)
  2871. throw Error(format("path `%1%' does not exist and cannot be created") % path, worker.exitStatus());
  2872. }
  2873. void LocalStore::repairPath(const Path & path)
  2874. {
  2875. Worker worker(*this);
  2876. GoalPtr goal = worker.makeSubstitutionGoal(path, true);
  2877. Goals goals = singleton<Goals>(goal);
  2878. worker.run(goals);
  2879. if (goal->getExitCode() != Goal::ecSuccess) {
  2880. /* Since substituting the path didn't work, if we have a valid
  2881. deriver, then rebuild the deriver. */
  2882. Path deriver = queryDeriver(path);
  2883. if (deriver != "" && isValidPath(deriver)) {
  2884. goals.clear();
  2885. goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair));
  2886. worker.run(goals);
  2887. } else
  2888. throw Error(format("cannot repair path `%1%'") % path, worker.exitStatus());
  2889. }
  2890. }
  2891. }