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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
#!/bin/sh
# -*- coding: utf-8; mode: ruby -*-
exec ruby -x "$0" "$@"
#!ruby
=begin rdoc
= mikutter - simple, powerful and moeful Mastodon client
Copyright (C) 2009-2024 Toshiaki Asai
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
=end
module Mikutter; end
Regexp.timeout = 1.0
if !ENV.fetch('DISABLE_BUNDLER_SETUP', nil) || ['', '0'].include?(ENV.fetch('DISABLE_BUNDLER_SETUP', nil).to_s)
begin
ENV['BUNDLE_GEMFILE'] = File.expand_path(File.join(File.dirname($0), "Gemfile"))
require 'bundler/setup'
rescue LoadError, SystemExit
# bundlerがないか、依存関係の解決に失敗した場合
# System の gem を使ってみる
end
end
require_relative 'core/miquire'
require 'boot/delayer'
require 'boot/option'
Mopt.parse exec_command: true
ENV['LIBOVERLAY_SCROLLBAR'] = '0'
require 'benchmark'
require 'thread'
require 'fileutils'
require 'lib/diva_hacks'
require 'lib/lazy'
require 'lib/reserver'
require 'lib/timelimitedqueue'
require 'lib/uithreadonly'
require 'lib/weakstorage'
require_relative 'core/utils'
require 'boot/check_config_permission'
require 'boot/mainloop'
require 'environment'
Dir.chdir(Environment::CONFROOT)
require 'system/system'
require 'boot/load_plugin'
Plugin.call(:boot, nil)
# イベントの待受を開始する。
# _profile_ がtrueなら、プロファイリングした結果を一時ディレクトリに保存する
def boot!(profile)
begin
RubyVM::YJIT.enable if RUBY_VERSION.split('.') >= %w[3 3]
if profile
require 'ruby-prof'
begin
notice 'start profiling'
RubyProf.start
Mainloop.mainloop
ensure
result = RubyProf.stop
printer = RubyProf::CallTreePrinter.new(result)
path = File.join(Environment::TMPDIR, 'profile', Time.new.strftime('%Y-%m-%d-%H%M%S'))
FileUtils.mkdir_p(path)
notice "profile: writing to #{path}"
printer.print(path: path)
notice "profile: done."
end
else
Mainloop.mainloop end
rescue => exception
into_debug_mode(exception)
notice "catch exception `#{exception.class}'"
raise
rescue Exception => exception
notice "catch exception `#{exception.class}'"
exception = Mainloop.exception_filter(exception)
notice "=> `#{exception.class}'"
raise end
exception = Mainloop.exception_filter(nil)
if exception
notice "raise mainloop exception `#{exception.class}'"
raise exception end
notice "boot! exited normally." end
def error_handling!(exception)
notice "catch #{exception.class}"
if Mopt.debug && exception.respond_to?(:deferred) && exception.deferred
if command_exist?('dot')
notice "[[#{exception.deferred.graph_draw}]]"
else
notice exception.deferred.graph
end
end
File.open(File.expand_path(File.join(Environment::TMPDIR, 'crashed_exception')), 'w'){ |io| Marshal.dump(exception, io) } rescue nil
raise exception end
begin
errfile = File.join(File.expand_path(Environment::TMPDIR), 'mikutter_dump')
File.rename(errfile, File.expand_path(File.join(Environment::TMPDIR, 'mikutter_error'))) if File.exist?(errfile)
if not Mopt.debug
$stderr = File.open(errfile, 'w')
def $stderr.write(string)
super(string)
self.fsync rescue nil
end
$logger = nil # 次の呼び出しから Kernel.logger の出力先が新しい stderr になるようにする
end
boot!(Mopt.profile)
if(Delayer.exception)
raise Delayer.exception end
rescue Interrupt, SystemExit, SignalException => exception
notice "catch #{exception.class}"
if Delayer.exception
error_handling! Delayer.exception
else
File.delete(errfile) if File.exist?(errfile)
raise exception end
rescue Exception => exception
error_handling! exception end
notice "mainloop exited normally."
|