Add some instrumentation for debugging GC leaks
This commit is contained in:
		
							parent
							
								
									d37d012774
								
							
						
					
					
						commit
						6e5b02bee4
					
				
					 4 changed files with 59 additions and 0 deletions
				
			
		|  | @ -230,6 +230,8 @@ EvalState::EvalState(const Strings & _searchPath) | ||||||
| 
 | 
 | ||||||
| EvalState::~EvalState() | EvalState::~EvalState() | ||||||
| { | { | ||||||
|  |     fileEvalCache.clear(); | ||||||
|  |     printCanaries(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1464,4 +1466,24 @@ void EvalState::printStats() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | void EvalState::printCanaries() | ||||||
|  | { | ||||||
|  | #if HAVE_BOEHMGC | ||||||
|  |     if (!settings.get("debug-gc", false)) return; | ||||||
|  | 
 | ||||||
|  |     GC_gcollect(); | ||||||
|  | 
 | ||||||
|  |     if (gcCanaries.empty()) { | ||||||
|  |         printMsg(lvlError, "all canaries have been garbage-collected"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     printMsg(lvlError, "the following canaries have not been garbage-collected:"); | ||||||
|  | 
 | ||||||
|  |     for (auto i : gcCanaries) | ||||||
|  |         printMsg(lvlError, format("  %1%") % i->string.s); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -255,6 +255,8 @@ public: | ||||||
|     /* Print statistics. */ |     /* Print statistics. */ | ||||||
|     void printStats(); |     void printStats(); | ||||||
| 
 | 
 | ||||||
|  |     void printCanaries(); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 
 | 
 | ||||||
|     unsigned long nrEnvs; |     unsigned long nrEnvs; | ||||||
|  | @ -285,6 +287,12 @@ private: | ||||||
|     friend struct ExprOpConcatLists; |     friend struct ExprOpConcatLists; | ||||||
|     friend struct ExprSelect; |     friend struct ExprSelect; | ||||||
|     friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); |     friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); | ||||||
|  | 
 | ||||||
|  | #if HAVE_BOEHMGC | ||||||
|  |     std::set<Value *> gcCanaries; | ||||||
|  |     friend void canaryFinalizer(GC_PTR obj, GC_PTR client_data); | ||||||
|  |     friend void prim_gcCanary(EvalState & state, const Pos & pos, Value * * args, Value & v); | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -397,6 +397,32 @@ static void prim_trace(EvalState & state, const Pos & pos, Value * * args, Value | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | #if HAVE_BOEHMGC | ||||||
|  | void canaryFinalizer(GC_PTR obj, GC_PTR client_data) | ||||||
|  | { | ||||||
|  |     Value * v = (Value *) obj; | ||||||
|  |     EvalState & state(* (EvalState *) client_data); | ||||||
|  |     printMsg(lvlError, format("canary ‘%1%’ garbage-collected") % v->string.s); | ||||||
|  |     auto i = state.gcCanaries.find(v); | ||||||
|  |     assert(i != state.gcCanaries.end()); | ||||||
|  |     state.gcCanaries.erase(i); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void prim_gcCanary(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
|  | { | ||||||
|  |     string s = state.forceStringNoCtx(*args[0], pos); | ||||||
|  |     state.mkList(v, 1); | ||||||
|  |     Value * canary = v.list.elems[0] = state.allocValue(); | ||||||
|  | #if HAVE_BOEHMGC | ||||||
|  |     state.gcCanaries.insert(canary); | ||||||
|  |     GC_register_finalizer(canary, canaryFinalizer, &state, 0, 0); | ||||||
|  | #endif | ||||||
|  |     mkString(*canary, s); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /*************************************************************
 | /*************************************************************
 | ||||||
|  * Derivations |  * Derivations | ||||||
|  *************************************************************/ |  *************************************************************/ | ||||||
|  | @ -1393,6 +1419,7 @@ void EvalState::createBaseEnv() | ||||||
|     addPrimOp("__tryEval", 1, prim_tryEval); |     addPrimOp("__tryEval", 1, prim_tryEval); | ||||||
|     addPrimOp("__getEnv", 1, prim_getEnv); |     addPrimOp("__getEnv", 1, prim_getEnv); | ||||||
|     addPrimOp("__trace", 2, prim_trace); |     addPrimOp("__trace", 2, prim_trace); | ||||||
|  |     addPrimOp("__gcCanary", 1, prim_gcCanary); | ||||||
| 
 | 
 | ||||||
|     // Paths
 |     // Paths
 | ||||||
|     addPrimOp("__toPath", 1, prim_toPath); |     addPrimOp("__toPath", 1, prim_toPath); | ||||||
|  |  | ||||||
|  | @ -86,6 +86,8 @@ void processExpr(EvalState & state, const Strings & attrPaths, | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     state.printCanaries(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue