Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: chrome/browser/ui/hung_plugin_tab_helper.cc

Issue 10909241: Generate dumps for relevant renderers when users kill a hung pepper plugin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Dump&kill in blocking pool instead of on IO thread. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/hang_monitor/hang_crash_dump_win.cc ('k') | ppapi/host/ppapi_host.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/hung_plugin_tab_helper.h" 5 #include "chrome/browser/ui/hung_plugin_tab_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/process.h"
8 #include "base/process_util.h" 10 #include "base/process_util.h"
11 #include "base/rand_util.h"
9 #include "build/build_config.h" 12 #include "build/build_config.h"
10 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h" 13 #include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
11 #include "chrome/browser/infobars/infobar.h" 14 #include "chrome/browser/infobars/infobar.h"
12 #include "chrome/browser/infobars/infobar_tab_helper.h" 15 #include "chrome/browser/infobars/infobar_tab_helper.h"
13 #include "chrome/browser/ui/tab_contents/tab_contents.h" 16 #include "chrome/browser/ui/tab_contents/tab_contents.h"
14 #include "chrome/common/chrome_notification_types.h" 17 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/chrome_version_info.h"
15 #include "content/public/browser/browser_child_process_host_iterator.h" 19 #include "content/public/browser/browser_child_process_host_iterator.h"
16 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/child_process_data.h" 21 #include "content/public/browser/child_process_data.h"
18 #include "content/public/browser/notification_details.h" 22 #include "content/public/browser/notification_details.h"
19 #include "content/public/browser/notification_service.h" 23 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/plugin_service.h" 24 #include "content/public/browser/plugin_service.h"
25 #include "content/public/browser/render_process_host.h"
21 #include "content/public/common/result_codes.h" 26 #include "content/public/common/result_codes.h"
22 #include "grit/chromium_strings.h" 27 #include "grit/chromium_strings.h"
23 #include "grit/generated_resources.h" 28 #include "grit/generated_resources.h"
24 #include "grit/locale_settings.h" 29 #include "grit/locale_settings.h"
25 #include "grit/theme_resources.h" 30 #include "grit/theme_resources.h"
26 #include "ui/base/l10n/l10n_util.h" 31 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h" 32 #include "ui/base/resource/resource_bundle.h"
28 33
29 #if defined(OS_WIN) 34 #if defined(OS_WIN)
35 #include "base/win/scoped_handle.h"
30 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h" 36 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
31 #endif 37 #endif
32 38
33 namespace { 39 namespace {
34 40
35 // Delay in seconds before re-showing the hung plugin message. This will be 41 // Delay in seconds before re-showing the hung plugin message. This will be
36 // increased each time. 42 // increased each time.
37 const int kInitialReshowDelaySec = 10; 43 const int kInitialReshowDelaySec = 10;
38 44
45 #if defined(OS_WIN)
46
47 const char kDumpChildProcessesSequenceName[] = "DumpChildProcesses";
48
49 class OwnedHandleVector {
50 public:
51 OwnedHandleVector() {}
52
53 ~OwnedHandleVector() {
54 for (std::vector<HANDLE>::const_iterator iter = data_.begin();
55 iter != data_.end(); ++iter) {
56 ::CloseHandle(*iter);
57 }
58 }
59
60 std::vector<HANDLE>& data() { return data_; }
61
62 private:
63 std::vector<HANDLE> data_;
64
65 DISALLOW_COPY_AND_ASSIGN(OwnedHandleVector);
66 };
67
68 void DumpRenderersInBlockingPool(OwnedHandleVector* renderer_handles) {
69 for (std::vector<HANDLE>::const_iterator iter =
70 renderer_handles->data().begin();
71 iter != renderer_handles->data().end(); ++iter) {
72 CrashDumpIfProcessHandlingPepper(*iter);
73 }
74 }
75
76 void DumpAndTerminatePluginInBlockingPool(
77 base::win::ScopedHandle* plugin_handle) {
78 CrashDumpAndTerminateHungChildProcess(plugin_handle->Get());
79 }
80
81 #endif
82
39 // Called on the I/O thread to actually kill the plugin with the given child 83 // Called on the I/O thread to actually kill the plugin with the given child
40 // ID. We specifically don't want this to be a member function since if the 84 // ID. We specifically don't want this to be a member function since if the
41 // user chooses to kill the plugin, we want to kill it even if they close the 85 // user chooses to kill the plugin, we want to kill it even if they close the
42 // tab first. 86 // tab first.
43 // 87 //
44 // Be careful with the child_id. It's supplied by the renderer which might be 88 // Be careful with the child_id. It's supplied by the renderer which might be
45 // hacked. 89 // hacked.
46 void KillPluginOnIOThread(int child_id) { 90 void KillPluginOnIOThread(int child_id) {
47 content::BrowserChildProcessHostIterator iter( 91 content::BrowserChildProcessHostIterator iter(
48 content::PROCESS_TYPE_PPAPI_PLUGIN); 92 content::PROCESS_TYPE_PPAPI_PLUGIN);
49 while (!iter.Done()) { 93 while (!iter.Done()) {
50 const content::ChildProcessData& data = iter.GetData(); 94 const content::ChildProcessData& data = iter.GetData();
51 if (data.id == child_id) { 95 if (data.id == child_id) {
52 #if defined(OS_WIN) 96 #if defined(OS_WIN)
53 CrashDumpAndTerminateHungChildProcess(data.handle); 97 HANDLE handle = NULL;
98 HANDLE current_process = ::GetCurrentProcess();
99 ::DuplicateHandle(current_process, data.handle, current_process, &handle,
100 0, FALSE, DUPLICATE_SAME_ACCESS);
101 // Run it in blocking pool so that it won't block the I/O thread. Besides,
102 // we would like to make sure that it happens after dumping renderers.
103 content::BrowserThread::PostBlockingPoolSequencedTask(
104 kDumpChildProcessesSequenceName, FROM_HERE,
105 base::Bind(&DumpAndTerminatePluginInBlockingPool,
106 base::Owned(new base::win::ScopedHandle(handle))));
54 #else 107 #else
55 base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false); 108 base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false);
56 #endif 109 #endif
57 break; 110 break;
58 } 111 }
59 ++iter; 112 ++iter;
60 } 113 }
61 // Ignore the case where we didn't find the plugin, it may have terminated 114 // Ignore the case where we didn't find the plugin, it may have terminated
62 // before this function could run. 115 // before this function could run.
63 } 116 }
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 i->first)); 284 i->first));
232 285
233 // Next time we do this, delay it twice as long to avoid being annoying. 286 // Next time we do this, delay it twice as long to avoid being annoying.
234 state->next_reshow_delay *= 2; 287 state->next_reshow_delay *= 2;
235 return; 288 return;
236 } 289 }
237 } 290 }
238 } 291 }
239 292
240 void HungPluginTabHelper::KillPlugin(int child_id) { 293 void HungPluginTabHelper::KillPlugin(int child_id) {
294 #if defined(OS_WIN)
295 // Dump renderers that are sending or receiving pepper messages, in order to
296 // diagnose inter-process deadlocks.
297 // Only do that on the Canary channel, for 20% of pepper plugin hangs.
298 if (base::RandInt(0, 100) < 20) {
299 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
300 if (channel == chrome::VersionInfo::CHANNEL_CANARY) {
301 scoped_ptr<OwnedHandleVector> renderer_handles(new OwnedHandleVector);
302 HANDLE current_process = ::GetCurrentProcess();
303 content::RenderProcessHost::iterator renderer_iter =
304 content::RenderProcessHost::AllHostsIterator();
305 for (; !renderer_iter.IsAtEnd(); renderer_iter.Advance()) {
306 content::RenderProcessHost* host = renderer_iter.GetCurrentValue();
307 HANDLE handle = NULL;
308 ::DuplicateHandle(current_process, host->GetHandle(), current_process,
309 &handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
310 renderer_handles->data().push_back(handle);
311 }
312 // If there are a lot of renderer processes, it is likely that we will
313 // generate too many crash dumps. They might not all be uploaded/recorded
314 // due to our crash dump uploading restrictions. So we just don't generate
315 // renderer crash dumps in that case.
316 if (renderer_handles->data().size() > 0 &&
317 renderer_handles->data().size() < 8) {
318 content::BrowserThread::PostBlockingPoolSequencedTask(
319 kDumpChildProcessesSequenceName, FROM_HERE,
320 base::Bind(&DumpRenderersInBlockingPool,
321 base::Owned(renderer_handles.release())));
322 }
323 }
324 }
325 #endif
326
241 PluginStateMap::iterator found = hung_plugins_.find(child_id); 327 PluginStateMap::iterator found = hung_plugins_.find(child_id);
242 if (found == hung_plugins_.end()) { 328 if (found == hung_plugins_.end()) {
243 NOTREACHED(); 329 NOTREACHED();
244 return; 330 return;
245 } 331 }
246 332
247 content::BrowserThread::PostTask(content::BrowserThread::IO, 333 content::BrowserThread::PostTask(content::BrowserThread::IO,
248 FROM_HERE, 334 FROM_HERE,
249 base::Bind(&KillPluginOnIOThread, child_id)); 335 base::Bind(&KillPluginOnIOThread, child_id));
250 CloseBar(found->second.get()); 336 CloseBar(found->second.get());
(...skipping 30 matching lines...) Expand all
281 state->info_bar = NULL; 367 state->info_bar = NULL;
282 } 368 }
283 } 369 }
284 370
285 InfoBarTabHelper* HungPluginTabHelper::GetInfoBarHelper() { 371 InfoBarTabHelper* HungPluginTabHelper::GetInfoBarHelper() {
286 TabContents* tab_contents = TabContents::FromWebContents(web_contents()); 372 TabContents* tab_contents = TabContents::FromWebContents(web_contents());
287 if (!tab_contents) 373 if (!tab_contents)
288 return NULL; 374 return NULL;
289 return tab_contents->infobar_tab_helper(); 375 return tab_contents->infobar_tab_helper();
290 } 376 }
OLDNEW
« no previous file with comments | « chrome/browser/hang_monitor/hang_crash_dump_win.cc ('k') | ppapi/host/ppapi_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698