Revert "fixed bug in lib/thread Queue"
[rbx.git] / kernel / loader.rb
bloba74144ea398754285f9c767d5114a21b77d7cee1
1 # Contained first is the system startup code.
3 # Re-setup all the stdio channels, to pull in new ivars
5 STDOUT.setup
6 STDIN.setup
7 STDERR.setup
9 begin
10   Array.after_loaded
11   Module.after_loaded
13   Class.after_loaded
14   Hash.after_loaded
15   Kernel.after_loaded
16   Math.after_loaded
17   FileTest.after_loaded
18   Thread.after_loaded
19   Struct.after_loaded
20   Signal.after_loaded
21   ObjectSpace.after_loaded
22   IO.after_loaded
23   IO::BidirectionalPipe.after_loaded
24   Object.after_loaded
25   File.after_loaded
26   String.after_loaded
28   Ar.after_loaded
30   ENV = EnvironmentVariables.new
32   # define a global "start time" to use for process calculation
33   $STARTUP_TIME = Time.now
34 rescue Object => e
35   STDOUT << "Error detected running loader startup stage:\n"
36   STDOUT << "  #{e.message} (#{e.class})\n"
37   STDOUT << e.backtrace
38   exit 2
39 end
41 # This is the end of the kernel and the beginning of specified
42 # code. We read out of ARGV to figure out what the user is
43 # trying to do.
45 Signal.action("INT") do |thr|
46   # We can't raise on ourselves, we raise on main.
47   if thr == Thread.current
48     thr = Thread.main
49   end
51   # The current thread might be dead if all other live threads are
52   # a sleep when the current one died.
53   unless thr.alive?
55     thr = Thread.main
56     # If main is dead too. Wow. Ok.. well... tell the user.
57     unless thr.alive?
58       puts "Signal received, but the main thread is dead."
59       puts "Unable to continue."
60       exit! 1
61     end
62   end
64   # Push the output down a little bit, makes things look more
65   # obvious that the system was interrupted.
66   puts
67   thr.raise Interrupt, "Thread has been interrupted"
68 end
70 # Setup $LOAD_PATH.
72 additions = []
74 # The main stdlib location
75 additions << Rubinius::CODE_PATH
77 $LOAD_PATH.insert($LOAD_PATH.index('.'), *additions)
79 if ENV['RUBYLIB'] and not ENV['RUBYLIB'].empty? then
80   $LOAD_PATH.unshift(*ENV['RUBYLIB'].split(':'))
81 end
83 # Pull it out now so that later unshifts don't obsure it.
84 main_lib = $LOAD_PATH.first
86 # Allow system wide code preloading
88 ['/etc/rbxrc',"#{ENV['HOME']}/.rbxrc",ENV['RBX_PRELOAD']].each do |file|
89   begin
90     load file if file and File.exist?(file)
91   rescue LoadError
92     nil
93   end
94 end
96 # Parse options here!
97 RBS_USAGE = <<END
98 Usage: rubinius [options] [file]
99   File may be any valid Ruby source file (.rb) or a compiled Ruby file (.rbc).
101 Options:
102   -d             Enable debugging output and set $DEBUG to true.
103   -dc            Display debugging information for the compiler.
104   -dl            Display debugging information for the loader.
105   -debug         Launch the debugger.
106   -remote-debug  Run the program under the control of a remote debugger.
107   -e 'code'      Directly compile and execute code (no file provided).
108   -Idir1[:dir2]  Add directories to $LOAD_PATH.
109   -S script      Run script using PATH environment variable to find it.
110   -p             Run the profiler.
111   -ps            Run the Selector profiler.
112   -pss           Run the SendSite profiler.
113   -rlibrary      Require library before execution.
114   -w             Enable warnings. (currently does nothing--compatibility)
115   -v             Display the version and set $VERBOSE to true.
118 $VERBOSE = false
119 code = 0
121 show_selectors = false
122 show_sendsites = false
124 # Setup the proper staticscope
125 MethodContext.current.method.staticscope = StaticScope.new(Object)
127 TOPLEVEL_BINDING = binding()
129 eval_code = nil
130 script = nil
132 begin
133   script_debug_requested = false
134   until ARGV.empty?
135     arg = ARGV.shift
136     case arg
137     when '--'
138       break
139     when '-h', '--help'
140       puts RBS_USAGE
141       exit 1
142     when "-v"
143       puts "rubinius #{RBX_VERSION} (ruby #{RUBY_VERSION} compatible) (#{Rubinius::BUILDREV[0..8]}) (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
144       $VERBOSE = true
145       exit 0 if ARGV.empty?
146     when "-w"
147       # do nothing (HACK)
148     when '-dc'
149       puts "[Compiler debugging enabled]"
150       $DEBUG_COMPILER = true
151     when '-dl'
152       $DEBUG_LOADING = true
153       puts "[Code loading debugging enabled]"
154     when '-d'
155       $DEBUG = true
156     when '-debug'
157       require 'debugger/interface'
158       Debugger::CmdLineInterface.new
159       script_debug_requested = true
160     when '-remote-debug'
161       require 'debugger/debug_server'
162       if port = (ARGV.first =~ /^\d+$/ and ARGV.shift)
163         $DEBUG_SERVER = Debugger::Server.new(port.to_i)
164       else
165         $DEBUG_SERVER = Debugger::Server.new
166       end
167       $DEBUG_SERVER.listen
168       script_debug_requested = true
169     when '-p'
170       require 'profile'
171     when '-ps'
172       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
173       show_selectors = count.to_i
174     when '-pss'
175       count = (ARGV.first =~ /^\d+$/) ? ARGV.shift : '30'
176       show_sendsites = count.to_i
177     when '-S'
178       script = ARGV.shift
179       sep    = File::PATH_SEPARATOR
180       path   = ENV['PATH'].split(sep).map { |d| File.join(d, script) }
181       file   = path.find { |path| File.exist? path }
183       $0 = script if file
185       # if missing, let it die a natural death
186       ARGV.unshift file ? file : script
187     when '-e'
188       $0 = "(eval)"
189       eval_code = ARGV.shift
190     else
191       if arg.prefix? "-I"
192         more = arg[2..-1]
193         if more.empty?
194           $LOAD_PATH.unshift(ARGV.shift)
195         else
196           more.split(":").reverse_each do |path|
197             $LOAD_PATH.unshift(path)
198           end
199         end
200       elsif arg.prefix? "-r"
201         more = arg[2..-1]
202         if more.empty?
203           require ARGV.shift
204         else
205           require more
206         end
207       elsif arg == "-"
208         $0 = "-"
209         Compile.execute STDIN.read
210       elsif arg.prefix? "-"
211         puts "Invalid switch '#{arg}'"
212         puts RBS_USAGE
213         exit! 1
214       else
215         script = arg
216         # And we're done.
217         break
218       end
219     end
220   end
222   # If someone used -e, run that code.
223   if eval_code
224     # If we also caught a script to run, we just treat it like
225     # another arg.
226     ARGV.unshift script if script
228     Compile.execute eval_code
229   elsif script
230     if File.exists?(script)
231       $0 = script
232       Compile.debug_script! if script_debug_requested
233       Compile.load_from_extension arg 
234     else
235       if script.suffix?(".rb")
236         puts "Unable to find '#{script}'"
237         exit! 1
238       else
239         prog = File.join main_lib, "bin", script
240         if File.exists? prog
241           $0 = prog
242           load prog
243         else
244           raise LoadError, "Unable to find a script '#{script}' to run"
245         end
246       end
247     end
248   end
250   unless $0
251     if Rubinius::Terminal
252       repr = ENV['RBX_REPR'] || "bin/irb"
253       $0 = repr
254       prog = File.join main_lib, repr
255       begin
256         load prog
257       rescue LoadError => e
258         STDERR.puts "Unable to find repr named '#{repr}' to load."
259         exit 1
260       end
261     else
262       $0 = "(eval)"
263       Compile.execute "p #{STDIN.read}"
264     end
265   end
266   
267 rescue SystemExit => e
268   code = e.status
269 rescue Object => e
270   begin
271     if e.kind_of? Exception or e.kind_of? ThrownValue
272       msg = e.message
273     else
274       msg = "strange object detected as exception: #{e.inspect}"
275     end
276     if e.kind_of? SyntaxError
277       puts "A syntax error has occured:"
278       puts "    #{msg}"
279       puts "    near line #{e.file}:#{e.line}, column #{e.column}"
280       puts "\nCode:\n#{e.code}"
281       if e.column
282         puts((" " * (e.column - 1)) + "^")
283       end
284     else
285       puts "An exception has occurred:"
286       puts "    #{msg} (#{e.class})"
287     end
288     puts "\nBacktrace:"
289     puts e.awesome_backtrace.show
290     code = 1
291   rescue Object => e2
292     puts "Unable to build backtrace due to errors"
293     puts "Original Exception: #{e.inspect} (#{e.class})"
294     puts "New Exception: #{e2.inspect} (#{e.class})"
295     code = 128
296   end
299 begin
300   Rubinius::AtExit.shift.call until Rubinius::AtExit.empty?
301 rescue SystemExit => e
302   code = e.status
303 rescue Object => e
304   puts "An exception occurred inside an at_exit handler:"
305   puts "    #{e.message} (#{e.class})"
306   puts "\nBacktrace:"
307   puts e.awesome_backtrace.show
308   code = 1
311 begin
312   ObjectSpace.run_finalizers
313 rescue Object => e
314   puts "An exception occured while running object finalizers:"
315   puts "    #{e.message} (#{e.class})"
316   puts "\nBacktrace:"
317   puts e.awesome_backtrace.show
318   code = 1
321 if show_selectors
322   ps = Sampler::Selectors.new
323   begin
324     ps.show_stats show_selectors
325   rescue Object => e
326     puts "An exception occured while running selector profiler:"
327     puts "    #{e.message} (#{e.class})"
328     puts "\nBacktrace:"
329     puts e.awesome_backtrace.show
330     code = 1
331   end
334 if show_sendsites
335   ps = Sampler::SendSites.new
336   begin
337     ps.show_stats show_sendsites
338   rescue Object => e
339     puts "An exception occured while running sendsite profiler:"
340     puts "    #{e.message} (#{e.class})"
341     puts "\nBacktrace:"
342     puts e.awesome_backtrace.show
343     code = 1
344   end
347 Process.exit(code || 0)