On Tue, Dec 06, 2005 at 10:03:46PM -0500, Ivan Nestlerode <[EMAIL PROTECTED]> was heard to say: > Package: aptitude > Version: 0.4.0-5 > Severity: important > > After running an update this evening, I found myself unable to use > aptitude as it kept getting stuck saying it was "Resolving dependencies". > > Basic operations on the preview screen would hang aptitude (trying to > upgrade something that was on hold, trying to put something on hold that > was broken, etc.). It was completely unusable (I had to kill it from > another window three times in a row). > > I have a large number of KDE packages on hold right now due to that > transition, so I thought maybe it was some combinatoric calculation that > was talking forever. However, aptitude doesn't peg the CPU or anything > when it is stuck like this. > > To be more specific, I start aptitude. I pressed "g". It said: > Resolving dependencies... > [Previous][Next][Appl][Close]
This part means that it hasn't come up with a solution yet and it's still thinking. However, it looks like it doesn't actually do anything. It looks like when its first tick count ran out, the background thread deadlocked instead of continuing to search for a solution. The subsequent hang is probably a secondary deadlock in the foreground thread when it tried to synchronize with the resolver thread. The attached patch should eliminate this deadlock. I'll hang onto the test data to see if I can use it to improve the resolver's performance on this rather nasty case in the future. Daniel
Wed Dec 7 20:50:54 PST 2005 Daniel Burrows <[EMAIL PROTECTED]> * Don't deadlock when the problem resolver runs out of ticks. diff -rN -udp old-head/src/ui.cc new-head/src/ui.cc --- old-head/src/ui.cc 2005-12-07 20:51:42.000000000 -0800 +++ new-head/src/ui.cc 2005-12-07 20:51:46.000000000 -0800 @@ -1567,7 +1567,7 @@ static void do_reload_cache() } #endif -static void start_solution_calculation(); +static void start_solution_calculation(bool blocking = true); class interactive_continuation : public resolver_manager::background_continuation { @@ -1630,7 +1630,7 @@ public: void no_more_time() { - start_solution_calculation(); + start_solution_calculation(false); } void interrupted() @@ -1639,8 +1639,12 @@ public: }; // If the current solution pointer is past the end of the solution -// list, queue up a calculation for it in the background thread. -static void start_solution_calculation() +// list, queue up a calculation for it in the background thread. If +// "blocking" is true, then the calling thread will wait for the +// background resolver thread to finish its calculation before +// returning from this function. IF THE CALLING THREAD IS THE +// BACKGROUND THREAD THIS WILL DEADLOCK IF BLOCKING IS TRUE! (see above for such a case) +static void start_solution_calculation(bool blocking) { resolver_manager::state state = resman->state_snapshot(); @@ -1648,15 +1652,22 @@ static void start_solution_calculation() state.selected_solution == state.generated_solutions && !state.solutions_exhausted && !state.background_thread_active) - resman->get_solution_background_blocking(resman->get_selected_solution(), - aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000), - aptcfg->FindI(PACKAGE "::ProblemResolver::WaitSteps", 50), - new interactive_continuation(resman)); + { + const int selected = state.selected_solution; + const int limit = aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000); + const int wait_steps = aptcfg->FindI(PACKAGE "::ProblemResolver::WaitSteps", 50); + interactive_continuation * const k = new interactive_continuation(resman); + + if(blocking) + resman->get_solution_background_blocking(selected, limit, wait_steps, k); + else + resman->get_solution_background(selected, limit, k); + } } static void do_connect_resolver_callback() { - resman->state_changed.connect(sigc::ptr_fun(&start_solution_calculation)); + resman->state_changed.connect(sigc::bind(sigc::ptr_fun(&start_solution_calculation), true)); // We may have missed a signal before making the connection: start_solution_calculation(); resman->state_changed.connect(sigc::ptr_fun(&vscreen_update));
signature.asc
Description: Digital signature