1. 程式人生 > >Ruby中迴圈引用導致lighttpd中的ruby fcgi指令碼執行失敗(Mac OS)

Ruby中迴圈引用導致lighttpd中的ruby fcgi指令碼執行失敗(Mac OS)

在另外一篇文章中我們說到了Ruby中的迴圈引用及檢查方法,迴圈引用在Ruby解析器看來只是一個警告,但是,這個告警會直接導致專案執行失敗。

我就遇到了這個問題,被這個問題阻塞了好幾天。下面詳細看這個案例。

我有一個執行在ruby中的lighttpd程式。
lighttpd中的配置為:

fastcgi.debug = 1
fastcgi.server = ( ".rb" =>
((
"bin-path" => "~/uproject/utopia-project-code/main/source/server/service/pmu_service/lighttpd_stub.rb",
#"bin-path" => "~/uproject/utopia-project-code/main/source/server/service/pmu_service/test.rb",
#"bin-path" => "~/.rvm/rubies/ruby-1.9.3-p125/bin/ruby",
"socket" => "/tmp/ruby.socket",
"check-local" => "disable"
))
)

lighttpd_stub.rb程式碼為:

#!/usr/local/ruby/bin/ruby
require_relative './main_service'

#start....
pmu_server = PMU_Service::PMUServer.get_instance
pmu_server.start_fcgi

上面引用到的核心fcgi程式碼為:

require 'fcgi'
require 'json'

require_relative '../pmu_dao/dao'
require_relative '../pmu_service/user_service'
require_relative '../pmu_dao/db_conn_pool'
require_relative '../pmu_communication/comm8n'
require_relative '../pmu_common/common'
...
def start_fcgi

FCGI.each_request do |fcgi|
@logger.info("receive a request: ")
fcgi_out = fcgi.out
fcgi_in = fcgi.in
#fcgi_env = fcgi.env

fcgi_out.print "Content-Type: application/json"
#should be 2 \r\n, else will be error
fcgi_out.print "\r\n\r\n"

#post param is a json string
post_param = get_post_param(fcgi_in)
@logger.info("get the input param from client: \n" + post_param)

if post_param == nil || post_param.empty?
@logger.info("empty input param")
fcgi_out.print "the is the empty page."
fcgi_out.print "\r\n\r\n"
else
#the json string containing the Header and the content
#so parse the Header object from json first
header = JSON.parse(post_param["data"]["Header"])
#then create a Message object for the dispatcher
message = PMU_COMM8N::Message.new(header, post_param["data"]["Content"])
#after dispatch return the HandlerResult object
resp_msg = @msg_disp.dispatch_message(message)
#write result to client
fcgi_out.print resp_msg
fcgi_out.print "\r\n\r\n"
end

fcgi.finish
end
end

請注意最上面的好幾個require_relative,這是引用專案中其他的ruby檔案,現在問題就在,require_relative ‘../pmu_service/user_service’,有迴圈引用的問題,通過 ruby -w 執行會輸出如下警告:

~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_handler.rb:6: warning: loading in progress, circular require considered harmful - ~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_service.rb
from main_service.rb:7:in `

'
from main_service.rb:7:in `require_relative'
from ~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_service.rb:7:in `'
from ~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_service.rb:7:in `require_relative'
from ~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_handler.rb:6:in `'
from ~/uproject/utopia-project-code/main/source/server/service/pmu_service/user_handler.rb:6:in `require_relative'

上面這個警告,要是真把其當作一個警告而忽略的話,就釀成大錯了。

我的lighttpd的fcgi每次處理請求的時候,就會報如下錯誤:

`block in start_fcgi': undefined method `[]' for nil:NilClass (NoMethodError)

錯誤對應的行是:

FCGI.each_request do |fcgi|

意思是FCGI.each_request裡面本身出問題了。

這個問題很怪異,但是修正迴圈引用後問題就消失了。所以迴圈引用對於應用層程式碼來說,就是一個bug。