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

Side by Side Diff: runtime/bin/vmstats_impl.cc

Issue 14313002: Added ctrl-\ support in dart binary to dump isolate stacks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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 | « runtime/bin/vmstats_impl.h ('k') | runtime/bin/vmstats_impl_android.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/vmstats_impl.h" 5 #include "bin/vmstats_impl.h"
6 6
7 #include "bin/file.h" 7 #include "bin/file.h"
8 #include "bin/log.h" 8 #include "bin/log.h"
9 #include "bin/platform.h" 9 #include "bin/platform.h"
10 #include "bin/resources.h" 10 #include "bin/resources.h"
11 #include "bin/socket.h" 11 #include "bin/socket.h"
12 #include "bin/thread.h" 12 #include "bin/thread.h"
13 #include "bin/utils.h" 13 #include "bin/utils.h"
14 #include "include/dart_debugger_api.h" 14 #include "include/dart_debugger_api.h"
15 #include "platform/json.h" 15 #include "platform/json.h"
16 16
17 #define BUFSIZE 8192 17 #define BUFSIZE 8192
18 #define RETRY_PAUSE 100 // milliseconds 18 #define RETRY_PAUSE 100 // milliseconds
19 19
20 static const char* INDEX_HTML = "index.html"; 20 static const char* INDEX_HTML = "index.html";
21 static const char* VMSTATS_HTML = "vmstats.html"; 21 static const char* VMSTATS_HTML = "vmstats.html";
22 static const char* DEFAULT_HOST = "localhost"; 22 static const char* DEFAULT_HOST = "localhost";
23 23
24 // Global static pointer used to ensure a single instance of the class. 24 // Global static pointer used to ensure a single instance of the class.
25 VmStats* VmStats::instance_ = NULL; 25 VmStats* VmStats::instance_ = NULL;
26 dart::Monitor* VmStats::instance_monitor_; 26 dart::Monitor* VmStats::instance_monitor_;
27 dart::Mutex* VmStatusService::mutex_; 27 dart::Mutex* VmStatusService::mutex_;
28 28
29 29
30 void VmStats::Start(int port, const char* root_dir) { 30 void VmStats::Start(int port, const char* root_dir, bool verbose) {
31 if (instance_ != NULL) { 31 if (instance_ != NULL) {
32 FATAL("VmStats already started."); 32 FATAL("VmStats already started.");
33 } 33 }
34 instance_ = new VmStats(); 34 instance_ = new VmStats(verbose);
35 instance_monitor_ = new dart::Monitor(); 35 instance_monitor_ = new dart::Monitor();
36 Initialize();
36 VmStatusService::InitOnce(); 37 VmStatusService::InitOnce();
38
39 if (port >= 0) {
40 StartServer(port, root_dir);
41 }
42 }
43
44
45 void VmStats::StartServer(int port, const char* root_dir) {
46 ASSERT(port >= 0);
47 ASSERT(instance_ != NULL);
48 ASSERT(instance_monitor_ != NULL);
37 Socket::Initialize(); 49 Socket::Initialize();
38 50
39 if (root_dir != NULL) { 51 if (root_dir != NULL) {
40 instance_->root_directory_ = root_dir; 52 instance_->root_directory_ = root_dir;
41 } 53 }
42 54
43 // TODO(tball): allow host to be specified. 55 // TODO(tball): allow host to be specified.
44 char* host = const_cast<char*>(DEFAULT_HOST); 56 char* host = const_cast<char*>(DEFAULT_HOST);
45 OSError* os_error; 57 OSError* os_error;
46 const char* host_ip = Socket::LookupIPv4Address(host, &os_error); 58 const char* host_ip = Socket::LookupIPv4Address(host, &os_error);
(...skipping 14 matching lines...) Expand all
61 73
62 MonitorLocker ml(instance_monitor_); 74 MonitorLocker ml(instance_monitor_);
63 instance_->running_ = true; 75 instance_->running_ = true;
64 int err = dart::Thread::Start(WebServer, address); 76 int err = dart::Thread::Start(WebServer, address);
65 if (err != 0) { 77 if (err != 0) {
66 Log::PrintErr("Failed starting VmStats thread: %d\n", err); 78 Log::PrintErr("Failed starting VmStats thread: %d\n", err);
67 Shutdown(); 79 Shutdown();
68 } 80 }
69 } 81 }
70 82
71
72 void VmStats::Stop() { 83 void VmStats::Stop() {
73 ASSERT(instance_ != NULL); 84 ASSERT(instance_ != NULL);
74 MonitorLocker ml(instance_monitor_); 85 MonitorLocker ml(instance_monitor_);
75 instance_->running_ = false; 86 instance_->running_ = false;
76 } 87 }
77 88
78 89
79 void VmStats::Shutdown() { 90 void VmStats::Shutdown() {
80 ASSERT(instance_ != NULL); 91 ASSERT(instance_ != NULL);
81 MonitorLocker ml(instance_monitor_); 92 MonitorLocker ml(instance_monitor_);
82 Socket::Close(instance_->bind_address_); 93 Socket::Close(instance_->bind_address_);
83 delete instance_; 94 delete instance_;
84 instance_ = NULL; 95 instance_ = NULL;
85 } 96 }
86 97
87 98
88 void VmStats::AddIsolate(IsolateData* isolate_data, 99 void VmStats::AddIsolate(IsolateData* isolate_data,
89 Dart_Isolate isolate) { 100 Dart_Isolate isolate) {
90 if (instance_ != NULL) { 101 MonitorLocker ml(instance_monitor_);
91 MonitorLocker ml(instance_monitor_); 102 instance_->isolate_table_[isolate_data] = isolate;
92 instance_->isolate_table_[isolate_data] = isolate;
93 }
94 } 103 }
95 104
96 105
97 void VmStats::RemoveIsolate(IsolateData* isolate_data) { 106 void VmStats::RemoveIsolate(IsolateData* isolate_data) {
98 if (instance_ != NULL) { 107 MonitorLocker ml(instance_monitor_);
99 MonitorLocker ml(instance_monitor_); 108 instance_->isolate_table_.erase(isolate_data);
100 instance_->isolate_table_.erase(isolate_data);
101 }
102 } 109 }
103 110
104 111
105 static const char* ContentType(const char* url) { 112 static const char* ContentType(const char* url) {
106 const char* suffix = strrchr(url, '.'); 113 const char* suffix = strrchr(url, '.');
107 if (suffix != NULL) { 114 if (suffix != NULL) {
108 if (!strcmp(suffix, ".html")) { 115 if (!strcmp(suffix, ".html")) {
109 return "text/html; charset=UTF-8"; 116 return "text/html; charset=UTF-8";
110 } 117 }
111 if (!strcmp(suffix, ".dart")) { 118 if (!strcmp(suffix, ".dart")) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 234
228 // Extract GET URL, and null-terminate URL in case request line has 235 // Extract GET URL, and null-terminate URL in case request line has
229 // HTTP version. 236 // HTTP version.
230 for (int i = 4; i < len; i++) { 237 for (int i = 4; i < len; i++) {
231 if (buffer[i] == ' ') { 238 if (buffer[i] == ' ') {
232 buffer[i] = '\0'; 239 buffer[i] = '\0';
233 } 240 }
234 } 241 }
235 char* url = strdup(&buffer[4]); 242 char* url = strdup(&buffer[4]);
236 243
237 Log::Print("vmstats: %s requested\n", url); 244 if (instance_->verbose_) {
245 Log::Print("vmstats: %s requested\n", url);
246 }
238 char* content = NULL; 247 char* content = NULL;
239 248
240 // Check for VmStats-specific URLs. 249 // Check for VmStats-specific URLs.
241 if (strcmp(url, "/isolates") == 0) { 250 if (strcmp(url, "/isolates") == 0) {
242 content = instance_->IsolatesStatus(); 251 content = instance_->IsolatesStatus();
243 } else { 252 } else {
244 // Check plug-ins. 253 // Check plug-ins.
245 content = VmStatusService::GetVmStatus(url); 254 content = VmStatusService::GetVmStatus(url);
246 } 255 }
247 256
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 IsolateTable::iterator itr; 316 IsolateTable::iterator itr;
308 bool first = true; 317 bool first = true;
309 for (itr = isolate_table_.begin(); itr != isolate_table_.end(); ++itr) { 318 for (itr = isolate_table_.begin(); itr != isolate_table_.end(); ++itr) {
310 Dart_Isolate isolate = itr->second; 319 Dart_Isolate isolate = itr->second;
311 static char request[512]; 320 static char request[512];
312 snprintf(request, sizeof(request), 321 snprintf(request, sizeof(request),
313 "/isolate/0x%"Px, 322 "/isolate/0x%"Px,
314 reinterpret_cast<intptr_t>(isolate)); 323 reinterpret_cast<intptr_t>(isolate));
315 char* status = VmStatusService::GetVmStatus(request); 324 char* status = VmStatusService::GetVmStatus(request);
316 if (status != NULL) { 325 if (status != NULL) {
317 text.AddString(status);
318 if (!first) { 326 if (!first) {
319 text.AddString(",\n"); 327 text.AddString(",\n");
320 } 328 }
329 text.AddString(status);
321 first = false; 330 first = false;
322 free(status); 331 free(status);
323 } 332 }
324 } 333 }
325 text.AddString("\n]\n}\n"); 334 text.AddString("\n]\n}\n");
326 return strdup(text.buf()); 335 return strdup(text.buf());
327 } 336 }
328 337
329 338
339 // Advance the scanner to the value token of a specified name-value pair.
340 void SeekNamedValue(const char* name, dart::JSONScanner* scanner) {
341 while (!scanner->EOM()) {
342 scanner->Scan();
343 if (scanner->IsStringLiteral(name)) {
344 scanner->Scan();
345 ASSERT(scanner->CurrentToken() == dart::JSONScanner::TokenColon);
346 scanner->Scan();
347 return;
348 }
349 }
350 }
351
352
353 // Windows doesn't have strndup(), so this is a simple, private version.
354 static char* StrNDup(const char* s, uword len) {
355 if (strlen(s) < len) {
356 len = strlen(s);
357 }
358 char* result = reinterpret_cast<char*>(malloc(len + 1));
359 memmove(result, s, len);
360 result[len + 1] = '\0';
361 return result;
362 }
363
364
365 void VmStats::DumpStackThread(uword unused) {
366 Log::Print("Isolate dump:\n");
367 IsolateTable::iterator itr;
368 MonitorLocker ml(instance_monitor_);
369 for (itr = instance_->isolate_table_.begin();
370 itr != instance_->isolate_table_.end(); ++itr) {
371 Dart_Isolate isolate = itr->second;
372
373 // Print isolate name and details.
374 static char buffer[512];
375 snprintf(buffer, sizeof(buffer),
376 "/isolate/0x%"Px, reinterpret_cast<intptr_t>(isolate));
377 char* isolate_details = VmStatusService::GetVmStatus(buffer);
378 if (isolate_details != NULL) {
379 dart::JSONScanner scanner(isolate_details);
380 SeekNamedValue("name", &scanner);
381 char* name = StrNDup(scanner.TokenChars(), scanner.TokenLen());
382 SeekNamedValue("port", &scanner);
383 char* port = StrNDup(scanner.TokenChars(), scanner.TokenLen());
384 Log::Print("\"%s\" port=%s\n", name, port);
385 free(isolate_details);
386 free(port);
387 free(name);
388 }
389
390 // Print stack trace.
391 snprintf(buffer, sizeof(buffer),
392 "/isolate/0x%"Px"/stacktrace",
393 reinterpret_cast<intptr_t>(isolate));
394 char* trace = VmStatusService::GetVmStatus(buffer);
395 if (trace != NULL) {
396 dart::JSONScanner scanner(trace);
397 while (true) {
398 SeekNamedValue("url", &scanner);
399 if (scanner.CurrentToken() == dart::JSONScanner::TokenEOM) {
400 break;
401 }
402 char* url = StrNDup(scanner.TokenChars(), scanner.TokenLen());
403 SeekNamedValue("line", &scanner);
404 char* line = StrNDup(scanner.TokenChars(), scanner.TokenLen());
405 SeekNamedValue("function", &scanner);
406 char* function = StrNDup(scanner.TokenChars(), scanner.TokenLen());
407 Log::Print(" at %s(%s:%s)\n", function, url, line);
408 free(url);
409 free(line);
410 free(function);
411 }
412 free(trace);
413 }
414 }
415 }
416
417
418 void VmStats::DumpStack() {
419 int err = dart::Thread::Start(DumpStackThread, 0);
420 if (err != 0) {
421 Log::PrintErr("Failed starting VmStats stackdump thread: %d\n", err);
422 Shutdown();
423 }
424 }
425
426
330 // Global static pointer used to ensure a single instance of the class. 427 // Global static pointer used to ensure a single instance of the class.
331 VmStatusService* VmStatusService::instance_ = NULL; 428 VmStatusService* VmStatusService::instance_ = NULL;
332 429
333 430
334 void VmStatusService::InitOnce() { 431 void VmStatusService::InitOnce() {
335 ASSERT(VmStatusService::instance_ == NULL); 432 ASSERT(VmStatusService::instance_ == NULL);
336 VmStatusService::instance_ = new VmStatusService(); 433 VmStatusService::instance_ = new VmStatusService();
337 VmStatusService::mutex_ = new dart::Mutex(); 434 VmStatusService::mutex_ = new dart::Mutex();
338 435
339 // Register built-in status plug-ins. RegisterPlugin is not used because 436 // Register built-in status plug-ins. RegisterPlugin is not used because
340 // this isn't called within an isolate, and because parameter checking 437 // this isn't called within an isolate, and because parameter checking
341 // isn't necessary. 438 // isn't necessary.
342 instance_->RegisterPlugin(&Dart_GetVmStatus); 439 instance_->RegisterPlugin(&Dart_GetVmStatus);
343 440
344 // TODO(tball): dynamically load any additional plug-ins. 441 // TODO(tball): dynamically load any additional plug-ins.
345 } 442 }
346 443
347 444
348 int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) { 445 int VmStatusService::RegisterPlugin(Dart_VmStatusCallback callback) {
446 ASSERT(VmStatusService::instance_ != NULL);
447 ASSERT(VmStatusService::mutex_ != NULL);
349 MutexLocker ml(mutex_); 448 MutexLocker ml(mutex_);
350 if (callback == NULL) { 449 if (callback == NULL) {
351 return -1; 450 return -1;
352 } 451 }
353 VmStatusPlugin* plugin = new VmStatusPlugin(callback); 452 VmStatusPlugin* plugin = new VmStatusPlugin(callback);
354 VmStatusPlugin* list = instance_->registered_plugin_list_; 453 VmStatusPlugin* list = instance_->registered_plugin_list_;
355 if (list == NULL) { 454 if (list == NULL) {
356 instance_->registered_plugin_list_ = plugin; 455 instance_->registered_plugin_list_ = plugin;
357 } else { 456 } else {
358 list->Append(plugin); 457 list->Append(plugin);
359 } 458 }
360 return 0; 459 return 0;
361 } 460 }
362 461
363 462
364 char* VmStatusService::GetVmStatus(const char* request) { 463 char* VmStatusService::GetVmStatus(const char* request) {
464 ASSERT(VmStatusService::instance_ != NULL);
365 VmStatusPlugin* plugin = instance_->registered_plugin_list_; 465 VmStatusPlugin* plugin = instance_->registered_plugin_list_;
366 while (plugin != NULL) { 466 while (plugin != NULL) {
367 char* result = (plugin->callback())(request); 467 char* result = (plugin->callback())(request);
368 if (result != NULL) { 468 if (result != NULL) {
369 return result; 469 return result;
370 } 470 }
371 plugin = plugin->next(); 471 plugin = plugin->next();
372 } 472 }
373 return NULL; 473 return NULL;
374 } 474 }
OLDNEW
« no previous file with comments | « runtime/bin/vmstats_impl.h ('k') | runtime/bin/vmstats_impl_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698