@@ -367,6 +367,8 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
367
367
{
368
368
UncheckedRoots unchecked;
369
369
370
+ std::string pids = std::to_string (getpid ());
371
+
370
372
auto procDir = AutoCloseDir{opendir (" /proc" )};
371
373
if (procDir) {
372
374
struct dirent * ent;
@@ -375,7 +377,7 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
375
377
auto storePathRegex = std::regex (quoteRegexChars (storeDir) + R"( /[0-9a-z]+[0-9a-zA-Z\+\-\._\?=]*)" );
376
378
while (errno = 0 , ent = readdir (procDir.get ())) {
377
379
checkInterrupt ();
378
- if (std::regex_match (ent->d_name , digitsRegex)) {
380
+ if (std::regex_match (ent->d_name , digitsRegex) && strcmp (pids. c_str (), ent-> d_name ) ) {
379
381
try {
380
382
readProcLink (fmt (" /proc/%s/exe" ,ent->d_name ), unchecked);
381
383
readProcLink (fmt (" /proc/%s/cwd" , ent->d_name ), unchecked);
@@ -469,7 +471,7 @@ struct GCLimitReached { };
469
471
470
472
void LocalStore::collectGarbage (const GCOptions & options, GCResults & results)
471
473
{
472
- bool shouldDelete = options. action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific ;
474
+ bool shouldDelete = std::holds_alternative<GCDelete>( options.action ) ;
473
475
bool gcKeepOutputs = settings.gcKeepOutputs ;
474
476
bool gcKeepDerivations = settings.gcKeepDerivations ;
475
477
@@ -494,10 +496,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
494
496
consequences if `keep-outputs' or `keep-derivations' are true
495
497
(the garbage collector will recurse into deleting the outputs
496
498
or derivers, respectively). So disable them. */
497
- if (options.action == GCOptions::gcDeleteSpecific && options.ignoreLiveness ) {
498
- gcKeepOutputs = false ;
499
- gcKeepDerivations = false ;
500
- }
499
+ std::visit (overloaded{[&](GCDelete del){
500
+ if (del.pathsToDelete .has_value () && del.ignoreLiveness ) {
501
+ gcKeepOutputs = false ;
502
+ gcKeepDerivations = false ;
503
+ }
504
+ }, [](GCReturn arg){}}, options.action );
501
505
502
506
if (shouldDelete)
503
507
deletePath (reservedPath);
@@ -617,8 +621,16 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
617
621
permanent roots cannot increase now. */
618
622
printInfo (" finding garbage collector roots..." );
619
623
Roots rootMap;
620
- if (!options.ignoreLiveness )
621
- findRootsNoTemp (rootMap, true );
624
+
625
+ std::visit (overloaded{
626
+ [&](GCDelete del) {
627
+ if (!del.ignoreLiveness )
628
+ findRootsNoTemp (rootMap, true );
629
+ },
630
+ [&](GCReturn r){
631
+ findRootsNoTemp (rootMap, true );
632
+ }},
633
+ options.action );
622
634
623
635
for (auto & i : rootMap) roots.insert (i.first );
624
636
@@ -721,9 +733,9 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
721
733
return markAlive ();
722
734
}
723
735
724
- if (options. action == GCOptions::gcDeleteSpecific
725
- && !options. pathsToDelete .count (*path))
726
- return ;
736
+ if (const GCDelete * del = std::get_if<GCDelete>(&options. action ))
737
+ if (del-> pathsToDelete . has_value () && !del-> pathsToDelete -> paths .count (*path))
738
+ return ;
727
739
728
740
{
729
741
auto hashPart = std::string (path->hashPart ());
@@ -781,27 +793,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
781
793
if (auto p = getEnv (" _NIX_TEST_GC_SYNC" ))
782
794
readFile (*p);
783
795
784
- /* Either delete all garbage paths, or just the specified
785
- paths (for gcDeleteSpecific). */
786
- if (options.action == GCOptions::gcDeleteSpecific || options.action == GCOptions::gcDeleteDead) {
787
-
788
- for (auto & i : options.pathsToDelete ) {
789
- deleteReferrersClosure (i);
790
- if (options.action == GCOptions::gcDeleteSpecific && !dead.count (i))
791
- throw Error (
792
- " Cannot delete path '%1%' since it is still alive. "
793
- " To find out why, use: "
794
- " nix-store --query --roots" ,
795
- printStorePath (i));
796
- }
797
-
798
- } else if (options.maxFreed > 0 ) {
799
-
800
- if (shouldDelete)
801
- printInfo (" deleting garbage..." );
802
- else
803
- printInfo (" determining live/dead paths..." );
804
-
796
+ auto findOrDeleteRoots = [&](){
805
797
try {
806
798
AutoCloseDir dir (opendir (realStoreDir.get ().c_str ()));
807
799
if (!dir) throw SysError (" opening directory '%1%'" , realStoreDir);
@@ -825,65 +817,87 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
825
817
}
826
818
} catch (GCLimitReached & e) {
827
819
}
828
- }
820
+ };
829
821
830
- if (options.action == GCOptions::gcReturnLive) {
831
- for (auto & i : alive)
832
- results.paths .insert (printStorePath (i));
833
- return ;
834
- }
822
+ /* Either delete all garbage paths, or just the specified
823
+ paths (for gcDeleteSpecific). */
824
+ std::visit (overloaded{
825
+ [&](GCDelete del){
826
+ if (del.pathsToDelete .has_value ()) {
827
+ for (auto & i : del.pathsToDelete ->paths ) {
828
+ deleteReferrersClosure (i);
829
+ if (!del.pathsToDelete ->skipAlive && !dead.count (i))
830
+ throw Error (
831
+ " Cannot delete path '%1%' since it is still alive. "
832
+ " To find out why, use: "
833
+ " nix-store --query --roots" ,
834
+ printStorePath (i));
835
+ }
836
+ } else if (options.maxFreed > 0 ) {
837
+ printInfo (" deleting garbage..." );
838
+ findOrDeleteRoots ();
839
+ }
835
840
836
- if (options. action == GCOptions::gcReturnDead) {
837
- for ( auto & i : dead)
838
- results. paths . insert ( printStorePath (i));
839
- return ;
840
- }
841
+ /* Unlink all files in /nix/store/.links that have a link count of 1,
842
+ which indicates that there are no other links and so they can be
843
+ safely deleted. FIXME: race condition with optimisePath(): we
844
+ might see a link count of 1 just before optimisePath() increases
845
+ the link count. */
841
846
842
- /* Unlink all files in /nix/store/.links that have a link count of 1,
843
- which indicates that there are no other links and so they can be
844
- safely deleted. FIXME: race condition with optimisePath(): we
845
- might see a link count of 1 just before optimisePath() increases
846
- the link count. */
847
- if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) {
848
- printInfo (" deleting unused links..." );
847
+ printInfo (" deleting unused links..." );
849
848
850
- AutoCloseDir dir (opendir (linksDir.c_str ()));
851
- if (!dir) throw SysError (" opening directory '%1%'" , linksDir);
849
+ AutoCloseDir dir (opendir (linksDir.c_str ()));
850
+ if (!dir) throw SysError (" opening directory '%1%'" , linksDir);
852
851
853
- int64_t actualSize = 0 , unsharedSize = 0 ;
852
+ int64_t actualSize = 0 , unsharedSize = 0 ;
854
853
855
- struct dirent * dirent;
856
- while (errno = 0 , dirent = readdir (dir.get ())) {
857
- checkInterrupt ();
858
- std::string name = dirent->d_name ;
859
- if (name == " ." || name == " .." ) continue ;
860
- Path path = linksDir + " /" + name;
854
+ struct dirent * dirent;
855
+ while (errno = 0 , dirent = readdir (dir.get ())) {
856
+ checkInterrupt ();
857
+ std::string name = dirent->d_name ;
858
+ if (name == " ." || name == " .." ) continue ;
859
+ Path path = linksDir + " /" + name;
861
860
862
- auto st = lstat (path);
861
+ auto st = lstat (path);
863
862
864
- if (st.st_nlink != 1 ) {
865
- actualSize += st.st_size ;
866
- unsharedSize += (st.st_nlink - 1 ) * st.st_size ;
867
- continue ;
868
- }
863
+ if (st.st_nlink != 1 ) {
864
+ actualSize += st.st_size ;
865
+ unsharedSize += (st.st_nlink - 1 ) * st.st_size ;
866
+ continue ;
867
+ }
869
868
870
- printMsg (lvlTalkative, " deleting unused link '%1%'" , path);
869
+ printMsg (lvlTalkative, " deleting unused link '%1%'" , path);
871
870
872
- if (unlink (path.c_str ()) == -1 )
873
- throw SysError (" deleting '%1%'" , path);
871
+ if (unlink (path.c_str ()) == -1 )
872
+ throw SysError (" deleting '%1%'" , path);
874
873
875
- /* Do not accound for deleted file here. Rely on deletePath()
876
- accounting. */
877
- }
874
+ /* Do not accound for deleted file here. Rely on deletePath()
875
+ accounting. */
876
+ }
878
877
879
- struct stat st;
880
- if (stat (linksDir.c_str (), &st) == -1 )
881
- throw SysError (" statting '%1%'" , linksDir);
882
- int64_t overhead = st.st_blocks * 512ULL ;
878
+ struct stat st;
879
+ if (stat (linksDir.c_str (), &st) == -1 )
880
+ throw SysError (" statting '%1%'" , linksDir);
881
+ int64_t overhead = st.st_blocks * 512ULL ;
883
882
884
- printInfo (" note: currently hard linking saves %.2f MiB" ,
885
- ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0 )));
886
- }
883
+ printInfo (" note: currently hard linking saves %.2f MiB" ,
884
+ ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0 )));
885
+ },
886
+ [&](GCReturn ret){
887
+ printInfo (" determining live/dead paths..." );
888
+ findOrDeleteRoots ();
889
+ if (ret == GCReturn::Live) {
890
+ for (auto & i : alive)
891
+ results.paths .insert (printStorePath (i));
892
+ return ;
893
+ }
894
+
895
+ if (ret == GCReturn::Dead) {
896
+ for (auto & i : dead)
897
+ results.paths .insert (printStorePath (i));
898
+ return ;
899
+ }
900
+ }}, options.action );
887
901
888
902
/* While we're at it, vacuum the database. */
889
903
// if (options.action == GCOptions::gcDeleteDead) vacuumDB();
@@ -945,8 +959,7 @@ void LocalStore::autoGC(bool sync)
945
959
promise.set_value ();
946
960
});
947
961
948
- GCOptions options;
949
- options.maxFreed = settings.maxFree - avail;
962
+ GCOptions options{.action = GCAction{GCDelete{}}, .maxFreed = settings.maxFree - avail};
950
963
951
964
printInfo (" running auto-GC to free %d bytes" , options.maxFreed );
952
965
0 commit comments