Type something to search...
method_missing 傳遞 splat argument 會噴 SystemStackError

method_missing 傳遞 splat argument 會噴 SystemStackError

  • Backend
  • 30 Sep, 2020

最近遇到一個因為 splat argument 導致噴 SystemStackError 的案例,研究了半天發現是使用 method_missing 才會遇到

最近工作上遇到一個案例,是呼叫某個函式會噴 SystemStackError,google 發現了類似的事情 https://github.com/redis/redis-rb/issues/264

Thanks for the report. This is now fixed on master. The problem was that some commands used argument splatting to pass their arguments to other functions. Argument splatting uses the Ruby stack, and can therefore result in a stack overflow when large arrays are splatted.

看起來是因為用 splat argument 傳遞參數太長導致 stack overflow。但是自己怎麼都無法簡單重現出來。

後來找到這個 https://bugs.ruby-lang.org/issues/10440 https://github.com/ruby/ruby/commit/5d1f152fa342f6bb5fa9b546e3971843ee81c6b1

發現在 Ruby 2.2 之後就解掉了,我自己裝 Ruby 2.1 的確就有辦法重現沒錯。不過工作用的環境是 Ruby 2.5.7 遇到的。

後來終於找到差異,原來是 method_missing 才會遇到:

class A
  def a(*args)
    puts args.size
  end
end
class B
  def method_missing(*args)
    puts args.size
  end
end
A.new.a(*(1..1_000_000).to_a) # => 1000000
B.new.b(*(1..1_000_000).to_a) # => SystemStackError: stack level too deep
Tags :
Share :

Related Posts

bullet gem 可能干擾對使用 preload 所造成效能影響的判定
bullet gem 可能干擾對使用 preload 所造成效能影響的判定

最近遇到了一個案例是,有個使用 includes 去 preload association 的地方,相對於直接 pluck 出來,花的時間慢的異常多。研究之後發現是 bullet 的 unused_eager_loading_enable 偵測打開後,會一定程度的影響效能。 如同這位開發者在 [issue](https://github.com/flyerhzm/bullet/issu

read more
CVE-2020–15169
CVE-2020–15169

來看看這個 CVE-2020–15169 漏洞是怎麼回事 看 https://github.com/advisories/GHSA-cfjv-5498-mph5 的說明可以知道,發生的時機在於,如果你使用了 [https://guides.rubyonrails.org/i18n.html#

read more
ActiveRecord 的 default_attributes
ActiveRecord 的 default_attributes

在 Rails server 沒有重開的情況下,更動資料庫表的欄位預設值,會有意想不到的事情發生 以下是用 Rails 6.0.3.2 + MySQL 5.6 實驗 事情是這樣的 有一張 tasks 表,有個欄位 completed,預設值為 false,且不能為 NULL create_table "tasks", options: "ENGI

read more
How to Update Your Pry Prompt Setting since v0.13.0
How to Update Your Pry Prompt Setting since v0.13.0

The pry gem changed itsPry::Prompt API since v0.13.0, and deprecated setting prompt through Pry.config.prompt = [] . If you have customized this way, you should use t

read more
ArgumentError: invalid byte sequence in UTF-8
ArgumentError: invalid byte sequence in UTF-8

有次遇到這個錯誤:ArgumentError: invalid byte sequence in UTF-8,一追之下發現是遇到類似這段程式碼, "english 中文\xED\xB6\xB0".gsub(/english/, '')會錯的原因是因為 \xED\xB6\xB0 不是合法的 UTF-8 編碼。 要檢查是不是合法的編碼可以用 `valid_encod

read more
Rack 的 Middleware 的執行順序
Rack 的 Middleware 的執行順序

看〈為你自己學 Ruby on Rails〉介紹 Rack 的 Middleware 執行順序看不太懂,於是就研究了一下原始碼,看看是怎麼回事 因為常常聽到 Middleware Middleware 的,但是又不太懂,於是在網路上找到龍哥寫的文章,非常簡顯易懂,跟著動手做可以知道 Rack 要怎麼使用。 但是在「Middleware 的順序?」這的章節看不太懂盤子的比喻,於是決定直接在看原始

read more
[Rails][MySQL] 使用 update_all + JOIN + LIMIT 需注意效能問題
[Rails][MySQL] 使用 update_all + JOIN + LIMIT 需注意效能問題

MySQL 使用 JOIN + update_all 時,若遇到 LIMIT 則會轉為 subquery,需注意效能問題。 Rails 在使用 update_all 時,如果有用到 JOIN,會改用 subquery 的形式改寫,但若 Adapter 為 MySQL 時就會維持,因為 MySQL 語法本身支援 JOIN + UPDATE。但若是包含 LIMIT 時,由於 MySQL 也不支援,所

read more
Ruby Concurrency 筆記
Ruby Concurrency 筆記

Ruby 3.0.0 在去年聖誕節推出,release note 提到了一些 concurrency 相關的新功能,一邊研究一邊做個紀錄 在 Ruby 3.0.0 Released 提到了 Ruby 針對 Concurrency 加入了 [`Fiber#sch

read more
使用 Arel 寫出好看的 Left Join
使用 Arel 寫出好看的 Left Join

之前想要寫有條件的 left join 都會寫成 raw SQL query 的字串,但是其實也可以用 Arel 寫出比較好看的程式碼。 假設有個 DB 的 schema 長這樣: create_table "posts", force: :cascade do |t| t.string "title" t.boolean "active" t.integer "u

read more
在 Rails 5.1 之後,使用 pluck 不保證會 DB query
在 Rails 5.1 之後,使用 pluck 不保證會 DB query

在 Rails 5.1 之後,因為這個 commit,為 pluck 的行為帶來的一點變動。 因為習慣在 Rails 4.2 開發,養成了一個直覺是使用 pluck 就是會 DB query。但是就在換

read more
好像搞懂 searchkick 的 field 到底是怎麼用的了
好像搞懂 searchkick 的 field 到底是怎麼用的了

之前在看 searchkick 的 Github README 時,一直搞不懂 field 這個單位到底是什麼,於是花了一點時間來研究, gem 本人在此: searchkick 這個 gem 是封裝了幾個 Elasticsearch 相關的 gem,讓我們用 ActiveRecord 的方式,去操作 Elasticsearch 的 API。 <LinkCard url="https://

read more
如何 preload polymorphic associations
如何 preload polymorphic associations

因為想要用 includes preload polymorphic associations,但是不同 model 後面的 association 對象不一樣時不能直接用。後來在網路上找到可以用 ActiveRecord::Associations::Preloader preload 已經初始化後的 records 來達到目的。 **備註:Rails 6 已經支援 preload p

read more
如何使用 batch-loader gem 避免 N+1 Query
如何使用 batch-loader gem 避免 N+1 Query

我一開始看 batch-loader 在 github 上的說明,一直看不懂到底該怎麼用,所以這邊紀錄一下它的用法。 這是一個基本的使用方式,可以從 accounts 從 DB 拿出對應的 users: def user_lazy(account) BatchLoader.for

read more
如何在 debug test case 時印出 DB 的 log
如何在 debug test case 時印出 DB 的 log

有時候會想利用 test case 去追蹤一些操作 DB 的行為。 像是會放 binding.pry 在要觀察的程式附近,接著只要用 ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)就可以把操作 DB 的 log 印到 terminal 的畫面了。

read more
如何在 IRB/Pry/Rails Console 使用 Up/Down 鍵搜尋以前打過的命令
如何在 IRB/Pry/Rails Console 使用 Up/Down 鍵搜尋以前打過的命令

覺得 Ctrl + R 的 reverse-i-search 用的不是很習慣,google 了一下原來這樣設定就可以用 up/down 鍵搜尋了。 新增 ~/.inputrc 檔案,裡面設定: "\e[A": history-search-backward "\e[B": history-search-forward

read more
如何無痛跑 rake task
如何無痛跑 rake task

用 Rails console 開 sandbox 模式 $ rails c -s先載入環境就可以跑了 > Rails.application.load_tasks > Rake::Task['some_namespace:some_task_name'].invoke由於對 DB 的操作之後都會 rollback,所以可以拿來測試 rake

read more
如何讓 whenever 排程執行的程式,噴錯時寫到 Rollbar
如何讓 whenever 排程執行的程式,噴錯時寫到 Rollbar

串接 Rollbar 的好處是可以方便監控伺服器噴錯。但是在使用 whenever 排程時執行程式時,有辦法在噴錯時也寫到 Rollbar 嗎? 如果是使用 sidekiq,無論是使用 include Sidekiq::Worker 產生的 [worker](https://github.com/mperham/sidekiq/wiki/G

read more
從 Arel 看 Visitor Pattern
從 Arel 看 Visitor Pattern

偶然發現,Arel 好像是用 visitor pattern,好奇心驅使之下,就來研究看看。 翻翻歷史 翻了一下 Arel 的 repo,發現它其實一開始並不是用 visitor pattern 的,是在 2.0.0 之後才重寫,如這個 [History](https://github

read more
設定可以跑 rails core repository 測試的開發環境
設定可以跑 rails core repository 測試的開發環境

記錄一下照著官方教學設定開發 rails core repository 的環境 以下步驟取自 https://github.com/rails/rails-dev-box:安裝 VirtualBox。Mac 如果安裝 VirtualBox 遇到權限問題,[要到 Security & Privacy 允許

read more