Am Montag, 5. Juni 2006 21:35 schrieb Bennett Helm:
> That does it. With more testing on both Qt-3 and Qt-4 versions, I  
> still can't get a crash.

I hoped that.

> (Does this patch work for LyX-1.4.x as well?)

No, take the attached one.


Georg
Index: src/lyx_cb.C
===================================================================
--- src/lyx_cb.C	(Revision 14013)
+++ src/lyx_cb.C	(Arbeitskopie)
@@ -216,7 +216,7 @@ void QuitLyX(bool noask)
 		Alert::warning(_("Unable to remove temporary directory"), msg);
 	}
 
-	lyx_gui::exit();
+	lyx_gui::exit(0);
 }
 
 
Index: src/frontends/gtk/lyx_gui.C
===================================================================
--- src/frontends/gtk/lyx_gui.C	(Revision 14013)
+++ src/frontends/gtk/lyx_gui.C	(Arbeitskopie)
@@ -99,7 +99,7 @@ int getDPI()
 } // namespace anon
 
 
-void lyx_gui::parse_init(int & argc, char * argv[])
+void lyx_gui::exec(int & argc, char * argv[])
 {
 	new Gtk::Main(argc, argv);
 
@@ -111,6 +111,8 @@ void lyx_gui::parse_init(int & argc, cha
 
 	// must do this /before/ lyxrc gets read
 	lyxrc.dpi = getDPI();
+
+	LyX::ref().exec2(argc, argv);
 }
 
 
@@ -150,8 +152,9 @@ void lyx_gui::start(string const & batch
 }
 
 
-void lyx_gui::exit()
+void lyx_gui::exit(int /*status*/)
 {
+	// FIXME: Don't ignore status
 	Gtk::Main::quit();
 }
 
Index: src/frontends/qt2/lyx_gui.C
===================================================================
--- src/frontends/qt2/lyx_gui.C	(Revision 14013)
+++ src/frontends/qt2/lyx_gui.C	(Arbeitskopie)
@@ -78,6 +78,10 @@ using std::string;
 
 extern BufferList bufferlist;
 
+// FIXME: wrong place !
+LyXServer * lyxserver;
+LyXServerSocket * lyxsocket;
+
 namespace {
 
 int getDPI()
@@ -89,11 +93,15 @@ int getDPI()
 
 map<int, shared_ptr<socket_callback> > socket_callbacks;
 
-} // namespace anon
+void cleanup()
+{
+	delete lyxsocket;
+	lyxsocket = 0;
+	delete lyxserver;
+	lyxserver = 0;
+}
 
-// FIXME: wrong place !
-LyXServer * lyxserver;
-LyXServerSocket * lyxsocket;
+} // namespace anon
 
 // in QLyXKeySym.C
 extern void initEncodings();
@@ -103,7 +111,6 @@ extern bool lyxX11EventFilter(XEvent * x
 #endif
 
 #ifdef Q_WS_MACX
-extern bool macEventFilter(EventRef event);
 extern pascal OSErr
 handleOpenDocuments(const AppleEvent* inEvent, AppleEvent* /*reply*/,
 		    long /*refCon*/);
@@ -157,22 +164,23 @@ namespace lyx_gui {
 
 bool use_gui = true;
 
-void parse_init(int & argc, char * argv[])
+
+void exec(int & argc, char * argv[])
 {
 	// Force adding of font path _before_ QApplication is initialized
 	FontLoader::initFontPath();
 
-	static LQApplication app(argc, argv);
+	LQApplication app(argc, argv);
 
 #if QT_VERSION >= 0x030200
 	// install translation file for Qt built-in dialogs
 	// These are only installed since Qt 3.2.x
-	static QTranslator qt_trans(0);
+	QTranslator qt_trans(0);
 	if (qt_trans.load(QString("qt_") + QTextCodec::locale(),
 			  qInstallPathTranslations())) {
-		app.installTranslator(&qt_trans);
+		qApp->installTranslator(&qt_trans);
 		// even if the language calls for RtL, don't do that
-		app.setReverseLayout(false);
+		qApp->setReverseLayout(false);
 		lyxerr[Debug::GUI]
 			<< "Successfully installed Qt translations for locale "
 			<< QTextCodec::locale() << std::endl;
@@ -186,7 +194,7 @@ void parse_init(int & argc, char * argv[
 	// These translations are meant to break Qt/Mac menu merging
 	// algorithm on some entries. It lists the menu names that
 	// should not be moved to the LyX menu
-	static QTranslator aqua_trans(0);
+	QTranslator aqua_trans(0);
 	aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setting", 0,
 					     "do_not_merge_me"));
 	aqua_trans.insert(QTranslatorMessage("QMenuBar", "Config", 0,
@@ -196,7 +204,7 @@ void parse_init(int & argc, char * argv[
 	aqua_trans.insert(QTranslatorMessage("QMenuBar", "Setup", 0,
 					     "do_not_merge_me"));
 
-	app.installTranslator(&aqua_trans);
+	qApp->installTranslator(&aqua_trans);
 #endif
 
 	using namespace lyx::graphics;
@@ -208,6 +216,8 @@ void parse_init(int & argc, char * argv[
 	lyxrc.dpi = getDPI();
 
 	LoaderQueue::setPriority(10,100);
+
+	LyX::ref().exec2(argc, argv);
 }
 
 
@@ -248,9 +258,7 @@ void start(string const & batch, vector<
 	qApp->exec();
 
 	// FIXME
-	delete lyxsocket;
-	delete lyxserver;
-	lyxserver = 0;
+	cleanup();
 }
 
 
@@ -266,18 +274,16 @@ void sync_events()
 }
 
 
-void exit()
+void exit(int status)
 {
-	delete lyxsocket;
-	delete lyxserver;
-	lyxserver = 0;
+	cleanup();
 
-	// we cannot call qApp->exit(0) - that could return us
+	// we cannot call QApplication::exit(status) - that could return us
 	// into a static dialog return in the lyx code (for example,
 	// load autosave file QMessageBox. We have to just get the hell
 	// out.
 
-	::exit(0);
+	::exit(status);
 }
 
 
Index: src/frontends/xforms/lyx_gui.C
===================================================================
--- src/frontends/xforms/lyx_gui.C	(Revision 14013)
+++ src/frontends/xforms/lyx_gui.C	(Arbeitskopie)
@@ -84,6 +84,7 @@ namespace {
 
 /// quit lyx
 bool finished = false;
+int exit_status = 0;
 
 /// estimate DPI from X server
 int getDPI()
@@ -153,7 +154,7 @@ namespace lyx_gui {
 bool use_gui = true;
 
 
-void parse_init(int & argc, char * argv[])
+void exec(int & argc, char * argv[])
 {
 	setDefaults();
 
@@ -198,6 +199,8 @@ void parse_init(int & argc, char * argv[
 	lyxrc.dpi = getDPI();
 
 	LoaderQueue::setPriority(10,100);
+
+	LyX::ref().exec2(argc, argv);
 }
 
 
@@ -327,12 +330,14 @@ void start(string const & batch, vector<
 	// FIXME: breaks emergencyCleanup
 	delete lyxsocket;
 	delete lyxserver;
+	::exit(exit_status);
 }
 
 
-void exit()
+void exit(int status)
 {
 	finished = true;
+	exit_status = status;
 }
 
 
Index: src/frontends/lyx_gui.h
===================================================================
--- src/frontends/lyx_gui.h	(Revision 14013)
+++ src/frontends/lyx_gui.h	(Arbeitskopie)
@@ -43,9 +43,6 @@ std::string const sans_font_name();
 /// return a suitable monospaced font name (called from non-gui context too !)
 std::string const typewriter_font_name();
 
-/// parse command line and do basic initialisation
-void parse_init(int & argc, char * argv[]);
-
 /**
  * set up GUI parameters. At this point lyxrc may
  * be used.
@@ -59,6 +56,11 @@ void parse_lyxrc();
 void start(std::string const & batch, std::vector<std::string> const & files);
 
 /**
+ * Enter the main event loop (\sa LyX::exec2)
+ */
+void exec(int & argc, char * argv[]);
+
+/**
  * Synchronise all pending events.
  */
 void sync_events();
@@ -66,7 +68,7 @@ void sync_events();
 /**
  * quit running LyX
  */
-void exit();
+void exit(int);
 
 /**
  * return the status flag for a given action. This can be used to tell
Index: src/lyx_main.C
===================================================================
--- src/lyx_main.C	(Revision 14013)
+++ src/lyx_main.C	(Arbeitskopie)
@@ -107,12 +107,20 @@ string cl_system_support;
 string cl_user_support;
 
 
+void lyx_exit(int status)
+{
+	if (lyx_gui::use_gui)
+		lyx_gui::exit(status);
+	exit(status);
+}
+
+
 void showFileError(string const & error)
 {
 	Alert::warning(_("Could not read configuration file"),
 		   bformat(_("Error while reading the configuration file\n%1$s.\n"
 		     "Please check your installation."), error));
-	exit(EXIT_FAILURE);
+	lyx_exit(EXIT_FAILURE);
 }
 
 
@@ -204,30 +212,37 @@ void LyX::priv_exec(int & argc, char * a
 {
 	// Here we need to parse the command line. At least
 	// we need to parse for "-dbg" and "-help"
-	bool const want_gui = easyParse(argc, argv);
+	lyx_gui::use_gui = easyParse(argc, argv);
 
 	lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
 				   lyx::support::top_build_dir_is_one_level_up);
 
-	if (want_gui)
-		lyx_gui::parse_init(argc, argv);
+	// Start the real execution loop.
+	if (lyx_gui::use_gui)
+		lyx_gui::exec(argc, argv);
+	else
+		exec2(argc, argv);
+}
+
 
+void LyX::exec2(int & argc, char * argv[])
+{
 	// check for any spurious extra arguments
 	// other than documents
 	for (int argi = 1; argi < argc ; ++argi) {
 		if (argv[argi][0] == '-') {
 			lyxerr << bformat(_("Wrong command line option `%1$s'. Exiting."),
 				argv[argi]) << endl;
-			exit(1);
+			lyx_exit(EXIT_FAILURE);
 		}
 	}
 
 	// Initialization of LyX (reads lyxrc and more)
 	lyxerr[Debug::INIT] << "Initializing LyX::init..." << endl;
-	init(want_gui);
+	init();
 	lyxerr[Debug::INIT] << "Initializing LyX::init...done" << endl;
 
-	if (want_gui)
+	if (lyx_gui::use_gui)
 		lyx_gui::parse_lyxrc();
 
 	vector<string> files;
@@ -276,12 +291,12 @@ void LyX::priv_exec(int & argc, char * a
 		files.clear(); // the files are already loaded
 	}
 
-	if (want_gui)
+	if (lyx_gui::use_gui)
 		lyx_gui::start(batch_command, files);
 	else {
 		// Something went wrong above
 		QuitLyX(false);
-		exit(EXIT_FAILURE);
+		lyx_exit(EXIT_FAILURE);
 	}
 }
 
@@ -379,7 +394,7 @@ static void error_handler(int err_sig)
 	if (err_sig == SIGSEGV || !getEnv("LYXDEBUG").empty())
 #endif
 		lyx::support::abort();
-	exit(0);
+	lyx_exit(EXIT_SUCCESS);
 }
 
 }
@@ -393,7 +408,7 @@ void LyX::printError(ErrorItem const & e
 }
 
 
-void LyX::init(bool gui)
+void LyX::init()
 {
 #ifdef SIGHUP
 	signal(SIGHUP, error_handler);
@@ -404,9 +419,6 @@ void LyX::init(bool gui)
 	signal(SIGTERM, error_handler);
 	// SIGPIPE can be safely ignored.
 
-	// Disable gui when easyparse says so
-	lyx_gui::use_gui = gui;
-
 	lyxrc.tempdir_path = package().temp_dir();
 	lyxrc.document_path = package().document_dir();
 
@@ -445,7 +457,7 @@ void LyX::init(bool gui)
 
 	// Check that user LyX directory is ok. We don't do that if
 	// running in batch mode.
-	if (gui) {
+	if (lyx_gui::use_gui) {
 		if (queryUserLyXDir(package().explicit_user_support()))
 			reconfigureUserLyXDir();
 	} else {
@@ -474,7 +486,7 @@ void LyX::init(bool gui)
 	lyxerr[Debug::INIT] << "Reading layouts..." << endl;
 	LyXSetStyle();
 
-	if (gui) {
+	if (lyx_gui::use_gui) {
 		// Set up bindings
 		toplevel_keymap.reset(new kb_keymap);
 		defaultKeyBindings(toplevel_keymap.get());
@@ -507,7 +519,7 @@ void LyX::init(bool gui)
 		// close to zero. We therefore don't try to overcome this
 		// problem with e.g. asking the user for a new path and
 		// trying again but simply exit.
-		exit(EXIT_FAILURE);
+		lyx_exit(EXIT_FAILURE);
 	}
 
 	if (lyxerr.debugging(Debug::INIT)) {
@@ -658,7 +670,7 @@ bool LyX::queryUserLyXDir(bool explicit_
 		    _("&Create directory"),
 		    _("&Exit LyX"))) {
 		lyxerr << _("No user LyX directory. Exiting.") << endl;
-		exit(1);
+		lyx_exit(EXIT_FAILURE);
 	}
 
 	lyxerr << bformat(_("LyX: Creating directory %1$s"),
@@ -669,7 +681,7 @@ bool LyX::queryUserLyXDir(bool explicit_
 		// Failed, so let's exit.
 		lyxerr << _("Failed to create directory. Exiting.")
 		       << endl;
-		exit(1);
+		lyx_exit(EXIT_FAILURE);
 	}
 
 	return true;
Index: src/lyx_main.h
===================================================================
--- src/lyx_main.h	(Revision 14013)
+++ src/lyx_main.h	(Arbeitskopie)
@@ -32,7 +32,21 @@ class kb_keymap;
 /// initial startup
 class LyX : boost::noncopyable {
 public:
+	/**
+	 * Execute LyX. The startup sequence is as follows:
+	 * -# LyX::exec()
+	 * -# LyX::priv_exec()
+	 * -# lyx_gui::exec()
+	 * -# LyX::exec2()
+	 * Step 3 is omitted if no gui is wanted. We need lyx_gui::exec()
+	 * only to create the QApplication object in the qt frontend. All
+	 * attempts with static and dynamically allocated QApplication
+	 * objects lead either to harmless error messages on exit
+	 * ("Mutex destroy failure") or crashes (OS X).
+	 */
 	static void exec(int & argc, char * argv[]);
+	/// Execute LyX (inner execution loop, \sa exec)
+	void exec2(int & argc, char * argv[]);
 	static LyX & ref();
 	static LyX const & cref();
 
@@ -56,7 +70,7 @@ private:
 	void priv_exec(int & argc, char * argv[]);
 
 	/// initial LyX set up
-	void init(bool);
+	void init();
 	/// set up the default key bindings
 	void defaultKeyBindings(kb_keymap * kbmap);
 	/// set up the default dead key bindings if requested

Reply via email to