Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apparently never ending "Indexing call sites..." #1694

Open
akimd opened this issue Mar 30, 2022 · 12 comments
Open

Apparently never ending "Indexing call sites..." #1694

akimd opened this issue Mar 30, 2022 · 12 comments

Comments

@akimd
Copy link

akimd commented Mar 30, 2022

Hi Justin,

Background

Brakeman version: 5.2.1
Rails version: 6.1.4.1
Ruby version: 2.7.2

Link to Rails application code: Sorry, I don't own the code, cannot do that. Besides I don't know what specific file would be responsible.

Hanging or Slowness

Please run Brakeman with --debug to see which file may be causing the issue.

I did that, and actually I'd like to know if there's a way for Brakeman to be even more verbose and to describe what it's doing in this "Indexing" phase. I have not stopped it, maybe it is still making progress, I do not know, and don't know how I could know.

It displayed this "Indexing" message four hours ago.

Cheers!

@akimd
Copy link
Author

akimd commented Mar 31, 2022

It's now been running for 20 hours.

@presidentbeef
Copy link
Owner

Hi @akimd - if Brakeman runs for more than ten minutes, there is probably something wrong.

No, there is no out-of-the-box way to get visibility into what's happening during the call indexing phase.

Is this a large codebase? Is Brakeman running in a memory-constrained environment?

@akimd
Copy link
Author

akimd commented Mar 31, 2022

Justin,

If you have a suggested diff to make it more verbose, I can do that.
Yes, the code base is quite large. wc -l on app/models say 462872 for instance.

But now that I ran ps on it, I can see that its state is "(interruptible) Sleeping".

It it run this way:

bundle exec brakeman --no-exit-on-warn --no-exit-on-error --output test/brakeman.json --parser-timeout 30 --skip-files app/views/user_login_attempts/_query_builder_filters_list.html.erb,...,app/views/specialties/_query_builder_filters_list.html.erb,app/views/search_bookmarks/_query_builder_filters_list.html.erb --safe-methods strip_tags -d -n

And ps aux says

USER     PID %CPU %MEM        VSZ       RSS TTY  STAT START   TIME COMMAND
xxx   968078  2.8  4.8 10.563.924 6.354.424 ?    S    Mar30  40:58 /gems/bin/brakeman --no-exit-on-warn --no-exit-on-error --output test/brakeman.json --parser-timeout 30 --skip-files app/views/user_login_attempts/_query_builder_filters_list.html.erb,...

Any idea what it might be waiting for?

@presidentbeef
Copy link
Owner

Honestly still think it's a memory issue.

I'll get back to you with a diff. If it's really stuck at call indexing, the debug flag isn't going to be helpful and in fact could be making the issue worse.

@presidentbeef
Copy link
Owner

@akimd

I'd try adding logging to lib/brakeman/tracker.rb to show progress during call indexing:

diff --git a/lib/brakeman/tracker.rb b/lib/brakeman/tracker.rb
index b6894f8b8..2b3c60c5d 100644
--- a/lib/brakeman/tracker.rb
+++ b/lib/brakeman/tracker.rb
@@ -253,21 +253,27 @@ class Brakeman::Tracker
     finder = Brakeman::FindAllCalls.new self
 
     self.each_method do |definition, set_name, method_name, file|
+      Brakeman.notify "[Call Index] #{file} #{set_name} #{method_name}"
       finder.process_source definition, :class => set_name, :method => method_name, :file => file
     end
 
     self.each_class do |definition, set_name, file|
+      Brakeman.notify "[Call Index] #{file} #{set_name}"
       finder.process_source definition, :class => set_name, :file => file
     end
 
     self.each_template do |_name, template|
+      Brakeman.notify "[Call Index] #{template.file}"
       finder.process_source template.src, :template => template, :file => template.file
     end
 
     self.initializers.each do |file_name, src|
+      Brakeman.notify "[Call Index] #{file_name}"
       finder.process_all_source src, :file => file_name
     end
 
+    Brakeman.notify "Creating call index..."
+
     @call_index = Brakeman::CallIndex.new finder.calls
   end

I'd also skip the -d flag.

I also recommend using a beefy machine with lots of free memory. Unfortunately Brakeman uses a lot of memory, especially for large applications.

You can also try the --faster and --skip-vendor flags to see if either or both of those help.

@akimd
Copy link
Author

akimd commented Apr 1, 2022

Hi Justin,
Thanks for the patch!
Now brakeman is stuck in a different state, but it seems to still be consuming some CPU:

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
XXXXXXXX 1069204 33.8  5.2 10419236 6926412 ?    D    14:11  35:47 /gems/bin/brakeman --no-exit-on-warn --no-exit-on-error --output test/brakeman.json --parser-timeout 30 --skip-files app/views/user_login_attempts/_query_builder_filters_list.html.erb,[...]

The man page says "D uninterruptible sleep (usually IO)".

The logs:

bundle exec brakeman --no-exit-on-warn --no-exit-on-error --output test/brakeman.json --parser-timeout 30 --skip-files app/views/user_login_attempts/_query_builder_filters_list.html.erb,[...] --safe-methods strip_tags
[...]
W, WARN -- : [Call Index] /app/app/views/app_archive_options/_result_list.html.erb
W, WARN -- : [Call Index] /app/app/views/app_archive_options/_select_active_show.html.erb
W, WARN -- : [Call Index] /app/app/views/app_archive_options/async_ongoing.html.erb
W, WARN -- : [Call Index] /app/app/views/app_archive_options/dev_menu.html.erb

There's nothing specific about this last file.

$ ls -l app/views/app_archive_options/dev_menu.html.erb
-rw-r--r-- 1 xxx xxx 64532 Feb 28 09:40 app/views/app_archive_options/dev_menu.html.erb

As a matter of fact it grokked other versions of it for other types of resources. I'll send that file to you privately.

I will also --skip it to see if that's exactly this file, or other would jam it the same way.

Wrt RAM, here's what I get on this machine (well, this image)

$ free
              total        used        free      shared  buff/cache   available
Mem:      131883128    69530292     5046332     8608256    57306504    53174536
Swap:     270532600    16853832   253678768

Cheers!

@akimd
Copy link
Author

akimd commented Apr 1, 2022

I'll send that file to you privately.

Couldn't find a way to do that :)

@akimd
Copy link
Author

akimd commented Apr 1, 2022

Hey, actually it still moves! It appeared to be stuck for a long while on [Call Index] /app/app/views/app_archive_options/dev_menu.html.erb, but it's gone further.

W, WARN -- : Creating call index...
W, WARN -- : Running checks in parallel...
[...]
W, WARN -- :  - CheckWithoutProtection
W, WARN -- :  - CheckXMLDoS
W, WARN -- :  - CheckYAMLParsing

and now it is back in Sl, i.e., state S but multithreaded (I had not passed -n this time).

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
xxxxxxxx 1069204 28.4  5.5 10790712 7299152 ?    Sl   14:11  39:28 /gems/bin/brakeman [...]

@akimd
Copy link
Author

akimd commented Apr 2, 2022

It eventually ended.

It started at 2022-04-01 14:11:46 and finished at 2022-04-01 17:53:05, in parallel.

I'll see if I can add timestamps to my logs to see what steps were really long.

@presidentbeef
Copy link
Owner

That's the longest successful run I've ever heard of.

Unless there is a really obvious root cause that you can easily reproduce with sample code, it's probably going to be hard to improve the situation without access to the source code of the Rails app.

@akimd
Copy link
Author

akimd commented Apr 6, 2022

Justin,
Yes, I understand all this. Is there a way for brakeman to spit statistics that could help me get an idea of what part of the app was so expensive to process? Or maybe just metrics.

@presidentbeef
Copy link
Owner

@akimd Not as-is, but adding logging for different stages is pretty easy. I can send you a diff, if you want.

Typically, though, there is some pathological case that causes an explosion of nodes in Brakeman. Figuring out where that's happening can be challenging... especially if an app takes hours to process.

Question... is it only the call indexing part that is slow? Or is it everything?

This is giving me flashbacks to 2012 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants