Example #1
0
        /// <summary>
        /// This method executes an async method on the main thread, but does not
        /// technically block the calling thread. It does however "loop" and pumps
        /// events in the mean time. This is a workaround for times when some of our
        /// model (which is aync) is called by an external party (i.e. Roslyn) which
        /// does not support async methods and potentially causes a deadlock.
        /// </summary>
        /// <param name="asyncMethod"></param>
        /// <remarks>See: https://github.com/mono/monodevelop/pull/7823</remarks>
        internal static void PumpingWait(Func <Task> asyncMethod)
        {
            // This method can be called by Roslyn or the editor in a context which is not the GTK UI context
            // that MonoDevelop uses. In that case, before starting async an operation that may queue
            // task continuations into the current context, we switch to the GTK context, so that
            // whatever is queued will be dispatched when we run RunPendingEvents.
            var oldContext = SynchronizationContext.Current;

            try {
                SynchronizationContext.SetSynchronizationContext(Runtime.MainSynchronizationContext);
                Task task = asyncMethod();
                // Can't wait for the task to finish synchronously since doing so would deadlock the UI thread.
                while (task != null && !task.IsCompleted)
                {
                    DispatchService.RunPendingEvents(30);
                }
            } finally {
                SynchronizationContext.SetSynchronizationContext(oldContext);
            }
        }
Example #2
0
        public static void Initialize(IProgressMonitor monitor)
        {
            Counters.Initialization.Trace("Creating Workbench");
            workbench = new Workbench();
            Counters.Initialization.Trace("Creating Root Workspace");
            workspace = new RootWorkspace();
            Counters.Initialization.Trace("Creating Services");
            projectOperations = new ProjectOperations();
            helpOperations    = new HelpOperations();
            commandService    = new CommandManager();
            ideServices       = new IdeServices();
            CustomToolService.Init();
            AutoTestService.Start(commandService, Preferences.EnableAutomatedTesting);

            commandService.CommandTargetScanStarted  += CommandServiceCommandTargetScanStarted;
            commandService.CommandTargetScanFinished += CommandServiceCommandTargetScanFinished;
            commandService.KeyBindingFailed          += KeyBindingFailed;

            KeyBindingService.LoadBindingsFromExtensionPath("/MonoDevelop/Ide/KeyBindingSchemes");
            KeyBindingService.LoadCurrentBindings("MD2");

            commandService.CommandError += delegate(object sender, CommandErrorArgs args) {
                LoggingService.LogInternalError(args.ErrorMessage, args.Exception);
            };

            FileService.ErrorHandler = FileServiceErrorHandler;

            monitor.BeginTask(GettextCatalog.GetString("Loading Workbench"), 5);
            Counters.Initialization.Trace("Loading Commands");

            commandService.LoadCommands("/MonoDevelop/Ide/Commands");
            monitor.Step(1);

            Counters.Initialization.Trace("Initializing Workbench");
            workbench.Initialize(monitor);
            monitor.Step(1);

            InternalLog.EnableErrorNotification();

            MonoDevelop.Ide.WelcomePage.WelcomePageService.Initialize();
            MonoDevelop.Ide.WelcomePage.WelcomePageService.ShowWelcomePage();

            monitor.Step(1);

            Counters.Initialization.Trace("Restoring Workbench State");
            workbench.Show("SharpDevelop.Workbench.WorkbenchMemento");
            monitor.Step(1);

            Counters.Initialization.Trace("Flushing GUI events");
            DispatchService.RunPendingEvents();
            Counters.Initialization.Trace("Flushed GUI events");

            MessageService.RootWindow = workbench.RootWindow;

            commandService.EnableIdleUpdate = true;

            // Perser service initialization
            TypeSystemService.TrackFileChanges            = true;
            TypeSystemService.ParseProgressMonitorFactory = new ParseProgressMonitorFactory();

            Customizer.OnIdeInitialized();

            // Startup commands
            Counters.Initialization.Trace("Running Startup Commands");
            AddinManager.AddExtensionNodeHandler("/MonoDevelop/Ide/StartupHandlers", OnExtensionChanged);
            monitor.Step(1);
            monitor.EndTask();

            // Set initial run flags
            Counters.Initialization.Trace("Upgrading Settings");

            if (PropertyService.Get("MonoDevelop.Core.FirstRun", false))
            {
                isInitialRun = true;
                PropertyService.Set("MonoDevelop.Core.FirstRun", false);
                PropertyService.Set("MonoDevelop.Core.LastRunVersion", BuildInfo.Version);
                PropertyService.Set("MonoDevelop.Core.LastRunRevision", CurrentRevision);
                PropertyService.SaveProperties();
            }

            string lastVersion  = PropertyService.Get("MonoDevelop.Core.LastRunVersion", "1.9.1");
            int    lastRevision = PropertyService.Get("MonoDevelop.Core.LastRunRevision", 0);

            if (lastRevision != CurrentRevision && !isInitialRun)
            {
                isInitialRunAfterUpgrade = true;
                if (lastRevision == 0)
                {
                    switch (lastVersion)
                    {
                    case "1.0": lastRevision = 1; break;

                    case "2.0": lastRevision = 2; break;

                    case "2.2": lastRevision = 3; break;

                    case "2.2.1": lastRevision = 4; break;
                    }
                }
                upgradedFromRevision = lastRevision;
                PropertyService.Set("MonoDevelop.Core.LastRunVersion", BuildInfo.Version);
                PropertyService.Set("MonoDevelop.Core.LastRunRevision", CurrentRevision);
                PropertyService.SaveProperties();
            }

            // The ide is now initialized

            isInitialized = true;

            if (isInitialRun)
            {
                try {
                    OnInitialRun();
                } catch (Exception e) {
                    LoggingService.LogError("Error found while initializing the IDE", e);
                }
            }

            if (isInitialRunAfterUpgrade)
            {
                try {
                    OnUpgraded(upgradedFromRevision);
                } catch (Exception e) {
                    LoggingService.LogError("Error found while initializing the IDE", e);
                }
            }

            if (initializedEvent != null)
            {
                initializedEvent(null, EventArgs.Empty);
                initializedEvent = null;
            }

            //FIXME: we should really make this on-demand. consumers can display a "loading help cache" message like VS
            MonoDevelop.Projects.HelpService.AsyncInitialize();

            UpdateInstrumentationIcon();
            IdeApp.Preferences.EnableInstrumentationChanged += delegate {
                UpdateInstrumentationIcon();
            };
            AutoTestService.NotifyEvent("MonoDevelop.Ide.IdeStart");
        }
Example #3
0
        int Run(MonoDevelopOptions options)
        {
            LoggingService.LogInfo("Starting {0} {1}", BrandingService.ApplicationLongName, IdeVersionInfo.MonoDevelopVersion);
            LoggingService.LogInfo("Build Information{0}{1}", Environment.NewLine, SystemInformation.GetBuildInformation());
            LoggingService.LogInfo("Running on {0}", RuntimeVersionInfo.GetRuntimeInfo());

            //ensure native libs initialized before we hit anything that p/invokes
            Platform.Initialize();
            sectionTimings ["PlatformInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            GettextCatalog.Initialize();
            sectionTimings ["GettextInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            LoggingService.LogInfo("Operating System: {0}", SystemInformation.GetOperatingSystemDescription());

            if (!Platform.IsWindows)
            {
                // The assembly resolver for MSBuild 15 assemblies needs to be defined early on.
                // Whilst Runtime.Initialize loads the MSBuild 15 assemblies from Mono this seems
                // to be too late to prevent the MEF composition and the static registrar from
                // failing to load the MonoDevelop.Ide assembly which now uses MSBuild 15 assemblies.
                ResolveMSBuildAssemblies();
            }

            Counters.Initialization.BeginTiming();

            if (options.PerfLog)
            {
                string logFile = Path.Combine(Environment.CurrentDirectory, "monodevelop.perf-log");
                LoggingService.LogInfo("Logging instrumentation service data to file: " + logFile);
                InstrumentationService.StartAutoSave(logFile, 1000);
            }

            Counters.Initialization.Trace("Initializing GTK");
            if (Platform.IsWindows && !CheckWindowsGtk())
            {
                return(1);
            }
            SetupExceptionManager();

            // explicit GLib type system initialization for GLib < 2.36 before any other type system access
            GLib.GType.Init();

            IdeApp.Customizer = options.IdeCustomizer ?? new IdeCustomizer();
            try {
                IdeApp.Customizer.Initialize();
            } catch (UnauthorizedAccessException ua) {
                LoggingService.LogError("Unauthorized access: " + ua.Message);
                return(1);
            }

            try {
                GLibLogging.Enabled = true;
            } catch (Exception ex) {
                LoggingService.LogError("Error initialising GLib logging.", ex);
            }

            var args = options.RemainingArgs.ToArray();

            IdeTheme.InitializeGtk(BrandingService.ApplicationName, ref args);

            sectionTimings["GtkInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();
            LoggingService.LogInfo("Using GTK+ {0}", IdeVersionInfo.GetGtkVersion());

            // XWT initialization
            FilePath p = typeof(IdeStartup).Assembly.Location;

            Runtime.LoadAssemblyFrom(p.ParentDirectory.Combine("Xwt.Gtk.dll"));
            Xwt.Application.InitializeAsGuest(Xwt.ToolkitType.Gtk);
            Xwt.Toolkit.CurrentEngine.RegisterBackend <IExtendedTitleBarWindowBackend, GtkExtendedTitleBarWindowBackend> ();
            Xwt.Toolkit.CurrentEngine.RegisterBackend <IExtendedTitleBarDialogBackend, GtkExtendedTitleBarDialogBackend> ();
            IdeTheme.SetupXwtTheme();

            sectionTimings["XwtInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            //default to Windows IME on Windows
            if (Platform.IsWindows && GtkWorkarounds.GtkMinorVersion >= 16)
            {
                var settings = Gtk.Settings.Default;
                var val      = GtkWorkarounds.GetProperty(settings, "gtk-im-module");
                if (string.IsNullOrEmpty(val.Val as string))
                {
                    GtkWorkarounds.SetProperty(settings, "gtk-im-module", new GLib.Value("ime"));
                }
            }

            string   socket_filename = null;
            EndPoint ep = null;

            DispatchService.Initialize();

            // Set a synchronization context for the main gtk thread
            SynchronizationContext.SetSynchronizationContext(DispatchService.SynchronizationContext);
            Runtime.MainSynchronizationContext = SynchronizationContext.Current;

            sectionTimings["DispatchInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            // Initialize Roslyn's synchronization context
            RoslynServices.RoslynService.Initialize();

            sectionTimings["RoslynInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            AddinManager.AddinLoadError += OnAddinError;

            var startupInfo = new StartupInfo(args);

            // If a combine was specified, force --newwindow.

            if (!options.NewWindow && startupInfo.HasFiles)
            {
                Counters.Initialization.Trace("Pre-Initializing Runtime to load files in existing window");
                Runtime.Initialize(true);
                foreach (var file in startupInfo.RequestedFileList)
                {
                    if (MonoDevelop.Projects.Services.ProjectService.IsWorkspaceItemFile(file.FileName))
                    {
                        options.NewWindow = true;
                        break;
                    }
                }
            }

            Counters.Initialization.Trace("Initializing Runtime");
            Runtime.Initialize(true);

            sectionTimings ["RuntimeInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            bool restartRequested = PropertyService.Get("MonoDevelop.Core.RestartRequested", false);

            startupInfo.Restarted = restartRequested;
            PropertyService.Set("MonoDevelop.Core.RestartRequested", false);

            IdeApp.Customizer.OnCoreInitialized();

            Counters.Initialization.Trace("Initializing theme");

            IdeTheme.SetupGtkTheme();

            sectionTimings["ThemeInitialized"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            ProgressMonitor monitor = new MonoDevelop.Core.ProgressMonitoring.ConsoleProgressMonitor();

            monitor.BeginTask(GettextCatalog.GetString("Starting {0}", BrandingService.ApplicationName), 2);

            //make sure that the platform service is initialised so that the Mac platform can subscribe to open-document events
            Counters.Initialization.Trace("Initializing Platform Service");
            DesktopService.Initialize();

            sectionTimings["PlatformInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            monitor.Step(1);

            if (options.IpcTcp)
            {
                listen_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
                ep            = new IPEndPoint(IPAddress.Loopback, ipcBasePort + HashSdbmBounded(Environment.UserName));
            }
            else
            {
                socket_filename = "/tmp/md-" + Environment.GetEnvironmentVariable("USER") + "-socket";
                listen_socket   = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
                ep = new UnixEndPoint(socket_filename);
            }

            // If not opening a combine, connect to existing monodevelop and pass filename(s) and exit
            if (!options.NewWindow && startupInfo.HasFiles)
            {
                try {
                    StringBuilder builder = new StringBuilder();
                    foreach (var file in startupInfo.RequestedFileList)
                    {
                        builder.AppendFormat("{0};{1};{2}\n", file.FileName, file.Line, file.Column);
                    }
                    listen_socket.Connect(ep);
                    listen_socket.Send(Encoding.UTF8.GetBytes(builder.ToString()));
                    return(0);
                } catch {
                    // Reset the socket
                    if (null != socket_filename && File.Exists(socket_filename))
                    {
                        File.Delete(socket_filename);
                    }
                }
            }

            Counters.Initialization.Trace("Checking System");

            CheckFileWatcher();

            sectionTimings["FileWatcherInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            Exception error            = null;
            int       reportedFailures = 0;

            try {
                Counters.Initialization.Trace("Loading Icons");
                //force initialisation before the workbench so that it can register stock icons for GTK before they get requested
                ImageService.Initialize();

                sectionTimings ["ImageInitialization"] = startupSectionTimer.ElapsedMilliseconds;
                startupSectionTimer.Restart();

                // If we display an error dialog before the main workbench window on OS X then a second application menu is created
                // which is then replaced with a second empty Apple menu.
                // XBC #33699
                Counters.Initialization.Trace("Initializing IdeApp");

                hideWelcomePage = startupInfo.HasFiles;
                IdeApp.Initialize(monitor, hideWelcomePage);
                sectionTimings ["AppInitialization"] = startupSectionTimer.ElapsedMilliseconds;
                startupSectionTimer.Restart();

                if (errorsList.Count > 0)
                {
                    using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog(errorsList.ToArray(), false)) {
                        if (!dlg.Run())
                        {
                            return(1);
                        }
                    }
                    reportedFailures = errorsList.Count;
                }

                if (!CheckSCPlugin())
                {
                    return(1);
                }

                // Load requested files
                Counters.Initialization.Trace("Opening Files");

                // load previous combine
                RecentFile openedProject = null;
                if (IdeApp.Preferences.LoadPrevSolutionOnStartup && !startupInfo.HasSolutionFile && !IdeApp.Workspace.WorkspaceItemIsOpening && !IdeApp.Workspace.IsOpen)
                {
                    openedProject = DesktopService.RecentFiles.MostRecentlyUsedProject;
                    if (openedProject != null)
                    {
                        var metadata = GetOpenWorkspaceOnStartupMetadata();
                        IdeApp.Workspace.OpenWorkspaceItem(openedProject.FileName, true, true, metadata).ContinueWith(t => IdeApp.OpenFiles(startupInfo.RequestedFileList, metadata), TaskScheduler.FromCurrentSynchronizationContext());
                        startupInfo.OpenedRecentProject = true;
                    }
                }
                if (openedProject == null)
                {
                    IdeApp.OpenFiles(startupInfo.RequestedFileList, GetOpenWorkspaceOnStartupMetadata());
                    startupInfo.OpenedFiles = startupInfo.HasFiles;
                }

                monitor.Step(1);
            } catch (Exception e) {
                error = e;
            } finally {
                monitor.Dispose();
            }

            if (error != null)
            {
                string message = BrandingService.BrandApplicationName(GettextCatalog.GetString("MonoDevelop failed to start"));
                MessageService.ShowFatalError(message, null, error);

                return(1);
            }

            if (errorsList.Count > reportedFailures)
            {
                using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog(errorsList.ToArray(), true))
                    dlg.Run();
            }

            errorsList = null;
            AddinManager.AddinLoadError -= OnAddinError;

            sectionTimings["BasicInitializationCompleted"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            // FIXME: we should probably track the last 'selected' one
            // and do this more cleanly
            try {
                listen_socket.Bind(ep);
                listen_socket.Listen(5);
                listen_socket.BeginAccept(new AsyncCallback(ListenCallback), listen_socket);
            } catch {
                // Socket already in use
            }

            sectionTimings["SocketInitialization"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            initialized = true;
            MessageService.RootWindow    = IdeApp.Workbench.RootWindow;
            Xwt.MessageDialog.RootWindow = Xwt.Toolkit.CurrentEngine.WrapWindow(IdeApp.Workbench.RootWindow);

            sectionTimings["WindowOpened"] = startupSectionTimer.ElapsedMilliseconds;
            startupSectionTimer.Restart();

            Thread.CurrentThread.Name = "GUI Thread";
            Counters.Initialization.Trace("Running IdeApp");
            Counters.Initialization.EndTiming();

            AddinManager.AddExtensionNodeHandler("/MonoDevelop/Ide/InitCompleteHandlers", OnExtensionChanged);
            StartLockupTracker();

            // This call is important so the current event loop is run before we run the main loop.
            // On Mac, the OpenDocuments event gets handled here, so we need to get the timeout
            // it queues before the OnIdle event so we can start opening a solution before
            // we show the main window.
            DispatchService.RunPendingEvents();

            sectionTimings ["PumpEventLoop"] = startupSectionTimer.ElapsedMilliseconds;
            startupTimer.Stop();
            startupSectionTimer.Stop();

            // Need to start this timer because we don't know yet if we've been asked to open a solution from the file manager.
            timeToCodeTimer.Start();
            ttcMetadata = new TimeToCodeMetadata {
                StartupTime = startupTimer.ElapsedMilliseconds
            };

            // Start this timer to limit the time to decide if the app was opened by a file manager
            IdeApp.StartFMOpenTimer(FMOpenTimerExpired);
            IdeApp.Workspace.FirstWorkspaceItemOpened += CompleteSolutionTimeToCode;
            IdeApp.Workbench.DocumentOpened           += CompleteFileTimeToCode;

            CreateStartupMetadata(startupInfo, sectionTimings);

            GLib.Idle.Add(OnIdle);
            IdeApp.Run();

            IdeApp.Customizer.OnIdeShutdown();

            // unloading services
            if (null != socket_filename)
            {
                File.Delete(socket_filename);
            }
            lockupCheckRunning = false;
            Runtime.Shutdown();

            IdeApp.Customizer.OnCoreShutdown();

            InstrumentationService.Stop();

            MonoDevelop.Components.GtkWorkarounds.Terminate();

            return(0);
        }
Example #4
0
        async Task <int> MainLoop(MonoDevelopOptions options, StartupInfo startupInfo)
        {
            ProgressMonitor monitor = new MonoDevelop.Core.ProgressMonitoring.ConsoleProgressMonitor();

            monitor.BeginTask(GettextCatalog.GetString("Starting {0}", BrandingService.ApplicationName), 2);

            //make sure that the platform service is initialised so that the Mac platform can subscribe to open-document events
            Counters.Initialization.Trace("Initializing Platform Service");
            await Runtime.GetService <DesktopService> ();

            IdeStartupTracker.StartupTracker.MarkSection("PlatformInitialization");

            monitor.Step(1);

            Counters.Initialization.Trace("Checking System");

            CheckFileWatcher();

            IdeStartupTracker.StartupTracker.MarkSection("FileWatcherInitialization");

            Exception error            = null;
            int       reportedFailures = 0;

            try {
                Counters.Initialization.Trace("Loading Icons");
                //force initialisation before the workbench so that it can register stock icons for GTK before they get requested
                ImageService.Initialize();

                IdeStartupTracker.StartupTracker.MarkSection("ImageInitialization");

                // If we display an error dialog before the main workbench window on OS X then a second application menu is created
                // which is then replaced with a second empty Apple menu.
                // XBC #33699
                Counters.Initialization.Trace("Initializing IdeApp");

                hideWelcomePage = options.NoStartWindow || startupInfo.HasFiles || IdeApp.Preferences.StartupBehaviour.Value != OnStartupBehaviour.ShowStartWindow;
                await IdeApp.Initialize(monitor);

                IdeStartupTracker.StartupTracker.MarkSection("AppInitialization");

                if (errorsList.Count > 0)
                {
                    using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog(errorsList.ToArray(), false)) {
                        if (!dlg.Run())
                        {
                            return(1);
                        }
                    }
                    reportedFailures = errorsList.Count;
                }

                if (!CheckSCPlugin())
                {
                    return(1);
                }

                // Load requested files
                Counters.Initialization.Trace("Opening Files");

                // load previous combine
                RecentFile openedProject = null;
                if (IdeApp.Preferences.StartupBehaviour.Value == OnStartupBehaviour.LoadPreviousSolution && !startupInfo.HasSolutionFile && !IdeApp.Workspace.WorkspaceItemIsOpening && !IdeApp.Workspace.IsOpen)
                {
                    openedProject = IdeServices.DesktopService.RecentFiles.MostRecentlyUsedProject;
                    if (openedProject != null)
                    {
                        var metadata = GetOpenWorkspaceOnStartupMetadata();
                        IdeApp.Workspace.OpenWorkspaceItem(openedProject.FileName, true, true, metadata).ContinueWith(t => IdeApp.OpenFiles(startupInfo.RequestedFileList, metadata), TaskScheduler.FromCurrentSynchronizationContext()).Ignore();
                        startupInfo.OpenedRecentProject = true;
                    }
                }
                if (openedProject == null)
                {
                    IdeApp.OpenFiles(startupInfo.RequestedFileList, GetOpenWorkspaceOnStartupMetadata());
                    startupInfo.OpenedFiles = startupInfo.HasFiles;
                }

                monitor.Step(1);
            } catch (Exception e) {
                error = e;
            } finally {
                monitor.Dispose();
            }

            if (error != null)
            {
                string message = BrandingService.BrandApplicationName(GettextCatalog.GetString("MonoDevelop failed to start"));
                message = message + "\n\n" + error.Message;
                MessageService.ShowFatalError(message, null, error);

                return(1);
            }

            if (errorsList.Count > reportedFailures)
            {
                using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog(errorsList.ToArray(), true))
                    dlg.Run();
            }

            errorsList = null;
            AddinManager.AddinLoadError -= OnAddinError;

            IdeStartupTracker.StartupTracker.MarkSection("BasicInitializationCompleted");

            instanceConnection.FileOpenRequested += (sender, a) => {
                foreach (var e in a)
                {
                    OpenFile(e.FileName);
                }
            };

            instanceConnection.StartListening();

            IdeStartupTracker.StartupTracker.MarkSection("SocketInitialization");

            initialized = true;
            MessageService.RootWindow    = IdeApp.Workbench.RootWindow;
            Xwt.MessageDialog.RootWindow = Xwt.Toolkit.CurrentEngine.WrapWindow(IdeApp.Workbench.RootWindow);

            IdeStartupTracker.StartupTracker.MarkSection("WindowOpened");

            Thread.CurrentThread.Name = "GUI Thread";
            Counters.Initialization.Trace("Running IdeApp");
            Counters.Initialization.EndTiming();

            AddinManager.AddExtensionNodeHandler("/MonoDevelop/Ide/InitCompleteHandlers", OnExtensionChanged);
            StartLockupTracker();

            // This call is important so the current event loop is run before we run the main loop.
            // On Mac, the OpenDocuments event gets handled here, so we need to get the timeout
            // it queues before the OnIdle event so we can start opening a solution before
            // we show the main window.
            DispatchService.RunPendingEvents();

            IdeStartupTracker.StartupTracker.MarkSection("PumpEventLoop");
            IdeStartupTracker.StartupTracker.Stop(startupInfo);

            GLib.Idle.Add(OnIdle);

            return(0);
        }