예제 #1
0
        private static void MaybeSendSigprof(int rss, long gc)
        {
            bool send_sigprof = false;

            try {
                if (prev_rss == -1 || prev_gc == -1)
                {
                    return;
                }

                // Log RSS increases of at least 5 megs or 5%
                if (rss - prev_rss >= 5 * 1024 ||
                    (double)rss / (double)prev_rss >= 1.05)
                {
                    send_sigprof = true;
                }

                // Log total object size increase of at least 10%.
                if ((double)gc / (double)prev_gc >= 1.1)
                {
                    send_sigprof = true;
                }
            } finally {
                prev_rss = rss;
                prev_gc  = gc;

                if (send_sigprof)
                {
                    Log.Debug("Suspicious memory size change detected.  Sending SIGPROF to ourself ({0})", sigprof_count++);
                    Mono.Unix.Native.Syscall.kill(System.Diagnostics.Process.GetCurrentProcess().Id, Mono.Unix.Native.Signum.SIGPROF);
                }
            }
        }
예제 #2
0
        private static void HandleSignal(int signal)
        {
            Logger.Log.Debug("Handling signal {0} ({1})", signal, (Mono.Unix.Native.Signum)signal);

            // Pass the signals to the helper too.
            GLib.Idle.Add(new GLib.IdleHandler(delegate()
            {
                RemoteIndexer.SignalRemoteIndexer((Mono.Unix.Native.Signum)signal);
                return(false);
            }));

            // If we get SIGUSR1, turn the debugging level up.
            if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR1)
            {
                LogLevel old_level = Log.Level;
                Log.Level = LogLevel.Debug;
                Log.Debug("Moving from log level {0} to Debug", old_level);
                return;
            }
            else if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR2)
            {
                // Debugging hook for beagrepd
                QueryDriver.DebugHook();
                LuceneCommon.DebugHook();
                return;
            }

            Logger.Log.Debug("Initiating shutdown in response to signal.");
            Shutdown.BeginShutdown();
        }
예제 #3
0
        private static void HandleSignal(int signal)
        {
            Log.Warn("Handling signal {0} ({1})", signal, (Mono.Unix.Native.Signum)signal);

            // If we get SIGUSR1, turn the debugging level up.
            if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR1)
            {
                LogLevel old_level = Log.Level;
                Log.Level = LogLevel.Debug;
                Log.Debug("Moving from log level {0} to Debug", old_level);
            }

            string span = StringFu.TimeSpanToString(DateTime.Now - last_activity);

            if (CurrentDisplayUri == null)
            {
                Log.Warn("Filtering status ({0} ago): no document is currently being filtered.", span);
            }
            else if (CurrentFilter == null)
            {
                Log.Warn("Filtering status ({0} ago): determining filter and extracting properties for {1} ({2})", span, CurrentDisplayUri, CurrentContentUri);
            }
            else
            {
                Log.Warn("Filtering status ({0} ago): extracting text from {1} ({2}) with {3}", span, CurrentDisplayUri, CurrentContentUri, CurrentFilter);
            }

            // Don't shut down on information signals (SIGUSR1 and SIGUSR2)
            if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR1 ||
                (Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR2)
            {
                return;
            }

            Logger.Log.Debug("Initiating shutdown in response to signal.");
            Shutdown.BeginShutdown();
        }
예제 #4
0
        public static bool StartupProcess()
        {
            // Profile our initialization
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            // Fire up our server
            if (!StartServer())
            {
                if (!arg_replace)
                {
                    Logger.Log.Error("Could not set up the listener for beagrep requests.  "
                                     + "There is probably another beagrepd instance running.  "
                                     + "Use --replace to replace the running service");
                    Environment.Exit(1);
                }

                ReplaceExisting();
            }

            // Set up out-of-process indexing
            LuceneQueryable.IndexerHook = new LuceneQueryable.IndexerCreator(RemoteIndexer.NewRemoteIndexer);

            Config config = Conf.Get(Conf.Names.DaemonConfig);

            // Initialize synchronization to keep the indexes local if PathFinder.StorageDir
            // is on a non-block device, or if BEAGREP_SYNCHRONIZE_LOCALLY is set

            if ((!SystemInformation.IsPathOnBlockDevice(PathFinder.StorageDir) &&
                 config.GetOption(Conf.Names.IndexSynchronization, true)) ||
                Environment.GetEnvironmentVariable("BEAGREP_SYNCHRONIZE_LOCALLY") != null)
            {
                IndexSynchronization.Initialize();
            }

            // Start the query driver.
            Logger.Log.Debug("Starting QueryDriver");
            QueryDriver.Start();

            // Start our battery monitor so we can shut down the
            // scheduler if needed.
            BatteryMonitor.Init();

            bool initially_on_battery = !BatteryMonitor.UsingAC && !config.GetOption(Conf.Names.IndexOnBattery, false);

            // Start the Global Scheduler thread
            if (!arg_disable_scheduler)
            {
                if (!initially_on_battery)
                {
                    Logger.Log.Debug("Starting Scheduler thread");
                    Scheduler.Global.Start();
                }
                else
                {
                    Log.Debug("Beagrep started on battery, not starting scheduler thread");
                }
            }

            // Start our Inotify threads
            Inotify.Start();

            // Test if the FileAdvise stuff is working: This will print a
            // warning if not.  The actual advice calls will fail silently.
            FileAdvise.TestAdvise();

#if ENABLE_AVAHI
            zeroconf = new Beagrep.Daemon.Network.Zeroconf();
#endif

            Conf.WatchForUpdates();

            stopwatch.Stop();

            Logger.Log.Debug("Daemon initialization finished after {0}", stopwatch);

            SystemInformation.LogMemoryUsage();

            if (arg_indexing_test_mode)
            {
                Thread.Sleep(1000);                  // Ugly paranoia: wait a second for the backends to settle.
                Logger.Log.Debug("Running in indexing test mode");
                Scheduler.Global.EmptyQueueEvent += OnEmptySchedulerQueue;
                Scheduler.Global.Add(null);                  // pulse the scheduler
            }

            return(false);
        }
예제 #5
0
        private static void DoMain(string [] args)
        {
            SystemInformation.SetProcessName("beagrepd-helper");

            bool run_by_hand = (Environment.GetEnvironmentVariable("BEAGREP_RUN_HELPER_BY_HAND") != null);
            bool log_in_fg   = (Environment.GetEnvironmentVariable("BEAGREP_LOG_IN_THE_FOREGROUND_PLEASE") != null);

            bool debug = false, disable_textcache = false;

            foreach (string arg in args)
            {
                if (arg == "--disable-text-cache")
                {
                    disable_textcache = true;
                }
                else if (arg == "--debug")
                {
                    debug = true;
                }
            }

            last_activity = DateTime.Now;

            Log.Initialize(PathFinder.LogDir,
                           "IndexHelper",
                           debug ? LogLevel.Debug : LogLevel.Warn,
                           run_by_hand || log_in_fg);

            Log.Always("Starting Index Helper process (version {0})", ExternalStringsHack.Version);
            Log.Always("Running on {0}", SystemInformation.MonoRuntimeVersion);
            Log.Always("Extended attributes are {0}", ExtendedAttribute.Supported ? "supported" : "not supported");
            Log.Always("Command Line: {0}",
                       Environment.CommandLine != null ? Environment.CommandLine : "(null)");
            if (disable_textcache)
            {
                Log.Always("Text cache is disabled.");
            }

            // Initialize GObject type system
            g_type_init();

            // Set the IO priority to idle, nice ourselves, and set
            // a batch scheduling policy so we that we play nice
            // on the system
            if (Environment.GetEnvironmentVariable("BEAGREP_EXERCISE_THE_DOG") != null)
            {
                Log.Always("BEAGREP_EXERCISE_THE_DOG is set");
            }

            Server.Init();

#if MONO_1_9
            Shutdown.SetupSignalHandlers(new Shutdown.SignalHandler(HandleSignal));
#else
            SetupSignalHandlers();
#endif

            Shutdown.ShutdownEvent += OnShutdown;

            main_loop = new MainLoop();
            Shutdown.RegisterMainLoop(main_loop);

            // Start the server
            Log.Debug("Starting messaging server");
            bool server_has_been_started = false;
            try {
                server = new Server("socket-helper", true, false);
                server.Start();
                server_has_been_started = true;
            } catch (InvalidOperationException ex) {
                Logger.Log.Error(ex, "Couldn't start server.  Exiting immediately.");
            }

            if (server_has_been_started)
            {
                // Whether we should generate heap-shot snapshots
                heap_shot = (Environment.GetEnvironmentVariable("_HEY_LETS_DO_A_HEAP_SHOT") != null);

                if (!run_by_hand)
                {
                    // Start the monitor thread, which keeps an eye on memory usage and idle time.
                    ExceptionHandlingThread.Start(new ThreadStart(MemoryAndIdleMonitorWorker));

                    // Start a thread that watches the daemon and begins a shutdown
                    // if it terminates.
                    ExceptionHandlingThread.Start(new ThreadStart(DaemonMonitorWorker));
                }

                // Start the main loop
                main_loop.Run();

                ExceptionHandlingThread.JoinAllThreads();

                // If we placed our sockets in a temp directory, try to clean it up
                // Note: this may fail because the daemon is still running
                if (PathFinder.GetRemoteStorageDir(false) != PathFinder.StorageDir)
                {
                    try {
                        Directory.Delete(PathFinder.GetRemoteStorageDir(false));
                    } catch (IOException) { }
                }

                Log.Always("Index helper process shut down cleanly.");
            }
        }
예제 #6
0
        private static void MemoryAndIdleMonitorWorker()
        {
            int vmrss_original = SystemInformation.VmRss;

            const double max_idle_time = 30;             // minutes

            const double threshold         = 5.0;
            const int    max_request_count = 0;
            int          last_vmrss        = 0;

            while (!Shutdown.ShutdownRequested)
            {
                double idle_time;
                idle_time = (DateTime.Now - last_activity).TotalMinutes;
                if (idle_time > max_idle_time && RemoteIndexerExecutor.Count > 0)
                {
                    Logger.Log.Debug("No activity for {0:0.0} minutes, shutting down", idle_time);
                    Shutdown.BeginShutdown();
                    return;
                }

                // Check resident memory usage
                int    vmrss = SystemInformation.VmRss;
                double size  = vmrss / (double)vmrss_original;
                if (last_vmrss != 0 && vmrss != last_vmrss)
                {
                    Logger.Log.Debug("Helper Size: VmRSS={0:0.0} MB, size={1:0.00}, {2:0.0}%",
                                     vmrss / 1024.0, size, 100.0 * (size - 1) / (threshold - 1));

                    double increase = vmrss / (double)last_vmrss;

                    if (heap_shot && increase > 1.20)
                    {
                        Log.Debug("Large memory increase detected.  Sending SIGPROF to ourself.");
                        Mono.Unix.Native.Syscall.kill(System.Diagnostics.Process.GetCurrentProcess().Id, Mono.Unix.Native.Signum.SIGPROF);
                    }
                }

                last_vmrss = vmrss;
                if (size > threshold ||
                    (max_request_count > 0 && RemoteIndexerExecutor.Count > max_request_count))
                {
                    if (RemoteIndexerExecutor.Count > 0)
                    {
                        Logger.Log.Debug("Process too big, shutting down!");
                        Shutdown.BeginShutdown();
                        return;
                    }
                    else
                    {
                        // Paranoia: don't shut down if we haven't done anything yet
                        Logger.Log.Debug("Deferring shutdown until we've actually done something.");
                        Thread.Sleep(1000);
                    }
                }
                else
                {
                    Thread.Sleep(3000);
                }
            }
        }