Apparently when using the three standard pipes (stdin, stdout, stderr)
in your own programming, it is REALLY easy to block or deadlock on
them. At first I figured there were problems in the ruby *open3
library, but this is not ruby specific, I found message board
discussions about similar problems using perl open3 libraries.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #http://github.com/ahoward/open4 is an alternative that handles pid and exit status #http://github.com/ahoward/session a more fleshed our shell utility require ‘open3’ Open3.popen3(“dc”) do |stdin, stdout, stderr| t = Thread.new(stderr) do |terr| while (line = terr.gets) puts “stderr: #{line}” end end puts “pushing 5 to stack” stdin.puts(5) puts “pushing 10 to stack” stdin.puts(10) puts “pushing + to stack” stdin.puts(”+”) puts “sending print command” stdin.puts(“p”) result = stdout.gets puts “stdout: #{ result }” puts “\ntrying an unsupported command” stdin.puts(“b”) extra_info_not_in_stderror = stdout.gets puts “stdout: #{extra_info_not_in_stderror}” puts “\nclosing stdin to avoid deadlock with stderr” stdin.close # puts “let’s give stderr a chance to run” # t.run or sleep 1 puts “joining” t.join end |
1 2 3 4 5 6 7 8 9 | #javac HelloWorld.java && jar cvf HelloWorld.jar HelloWorld.class require ‘java’ require ‘HelloWorld.jar’ import ‘HelloWorld’ puts HelloWorld.new.hello #=> “Hello cruel world” #jruby hello_world.rb |
1 2 3 4 5 6 7 8 9 | #javac HelloWorld.java && jar cvf HelloWorld.jar HelloWorld.class require ‘java’ require ‘HelloWorld.jar’ import ‘HelloWorld’ puts HelloWorld.new.hello #=> “Hello cruel world” #jruby hello_world.rb |
If you are on Rails 2.3.x (pre-Bundler) and want to organize some of your shared functionality into gems, but they are for internal use only, you could set-up a private gem server and point the :source at this server. And then you could deal with authentication, and then…
Or as a quick hack you could just allow for config.gem to reference the gemfile directly, which would then mean ‘rake gems:install’ would work, even if the gem were stored locally, or on a file-server, etc. Also useful as you could then just point at a .gem file on github.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ## require in config/environment.rb before init starts #require ‘config/add_explicit_path_to_config_gem’ #Rails::Initializer.run do |config| #config.gem ‘my_gem’, :version => ‘0.0.1’, :explicit_path => “#{RAILS_ROOT}/vendor/local_gemfiles/my_gem-0.0.1.gem” #or #config.gem ‘my_gem’, :version => ‘0.0.1’, :explicit_path => “http://github.com/myname/myrepo/raw/master/mygem.gem” #or module Rails class GemDependency def initialize_with_explicit_path(name, options = {}) @explicit_path = options[:explicit_path] initialize_without_explicit_path(name, options = {}) end alias_method_chain :initialize, :explicit_path private def install_command cmd = %w(install) « (@explicit_path || name) cmd « “—version” « %(“#{requirement.to_s}”) if requirement cmd « “—source” « @source if @source cmd end end end |
If you have a Rails metals that has enough code to have its own subdirectories that live in your Rails load_paths you can get stuck in dependency hell. The combinations of autoloading, rails reloading on development, and running through the metal can intersect in nasty ways: on the first request you get “Object is not missing constant XXX” and subsequent requests kick off “A copy of YYY has been removed from the module tree but is still active.”
The easiest solution is to kill magic reloading for this metal’s code by adding the metal’s directories of code to the Rails load_once_paths and then using explicit require_dependency calls for any files that give you trouble. For example, I have a MadMetal that referenced a Mad which has a whole sub-directory structure of code that, for now, lives under lib/mad:
#config/environment.rb config.load_once_paths += Dir["#{RAILS_ROOT}/lib/mad/**/"] #app/metal/mad_metal.rb require_dependency 'mad' class MadMetal def self.call(env) if (env["PATH_INFO"] == '/the_path_to_my_metal') Mad.call(env) else [404, {"Content-Type" => "text/html"}, ["Not Found"]] end end end And wallah, no more conflicts between development auto-reloading and metal.
Of course, now you need to restart the server if you change code in lib/mad. In this case it’s not a problem for me because the app is also a stand-alone rack app that I run with shotgun when I want development environment reloading.
#environment.rb
config.load_paths += Dir["#{RAILS_ROOT}/lib/mad/**/"]" #app/metal/mad_metal.rb
require_dependency 'mad'
class MadMetal
def self.call(env)
if (env["PATH_INFO"] == '/mad/')
Mad.call(env)
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
end
And wallah, no more conflicts between development auto-reloading and metal. Of course, now you need to restart the server if you change code in
Either add this to your .git/config
[alias] datetag = !git tag `git name-rev --name-only HEAD`-`date \"+%Y%m%d%H%M\"` or run it in your project folder to add it to the config for that project:
git config alias.datetag '!git tag `git name-rev --name-only HEAD`-`date "+%Y%m%d%H%M"`'
Either add this to your .git/config [alias]:
datetag = !git tag `git name-rev --name-only HEAD`-`date \"+%Y%m%d%H%M\"` or run it in your project folder to add it to the config for that project:
git config alias.datetag '!git tag `git name-rev --name-only HEAD`-`date "+%Y%m%d%H%M"`'
SetEnv RAILS_ENV staging
SetEnv RAILS_ENV staging