Use a different implementation of EventHook().  The new version
registers an input file handler for stdin with Tcl and handles Tcl
events until something is available on stdin; it then deletes the
handler and returns from EventHook().

This works with or without GNU readline, and doesn't busy-wait.

It still doesn't work for Mac or Windows :-(
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index b4f4d56..f63bd38 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -83,6 +83,24 @@
 #define HAVE_CREATEFILEHANDLER
 #endif
 
+#ifdef MS_WINDOWS
+#define FHANDLETYPE TCL_WIN_SOCKET
+#else
+#define FHANDLETYPE TCL_UNIX_FD
+#endif
+
+#if TKMAJORMINOR < 8000
+#define FHANDLE Tcl_File
+#define MAKEFHANDLE(fd) Tcl_GetFile((ClientData)(fd), FHANDLETYPE)
+#else
+#define FHANDLE int
+#define MAKEFHANDLE(fd) (fd)
+#endif
+
+#if defined(HAVE_CREATEFILEHANDLER) && !defined(MS_WINDOWS)
+#define WAIT_FOR_STDIN
+#endif
+
 extern int Tk_GetNumMainWindows();
 
 #ifdef macintosh
@@ -342,6 +360,10 @@
 /* Initialize the Tk application; see the `main' function in
  * `tkMain.c'.
  */
+
+static void EnableEventHook(); /* Forward */
+static void DisableEventHook(); /* Forward */
+
 static TkappObject *
 Tkapp_New(screenName, baseName, className, interactive)
 	char *screenName;
@@ -392,6 +414,8 @@
 	if (Tcl_AppInit(v->interp) != TCL_OK)
 		return (TkappObject *)Tkinter_Error(v);
 
+	EnableEventHook();
+
 	return v;
 }
 
@@ -1128,9 +1152,7 @@
 	PyObject *file, *func, *data;
 	PyObject *idkey;
 	int mask, id;
-#if TKMAJORMINOR < 8000
-	Tcl_File tfile;
-#endif
+	FHANDLE tfile;
 
 	if (!Tkapp_ClientDataDict) {
 		if (!(Tkapp_ClientDataDict = PyDict_New()))
@@ -1159,18 +1181,9 @@
 	}
 	Py_DECREF(idkey);
 
-#if TKMAJORMINOR < 8000
-#ifdef MS_WINDOWS
-	/* We assume this is a socket... */
-	tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
-#else /* !MS_WINDOWS */
-	tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
-#endif /* !MS_WINDOWS */
+	tfile = MAKEFHANDLE(id);
 	/* Ought to check for null Tcl_File object... */
 	Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
-#else /* >= 8000 */
-	Tcl_CreateFileHandler(id, mask, FileHandler, (ClientData) data);
-#endif  /* >= 8000 */
 	/* XXX fileHandlerDict */
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -1186,9 +1199,7 @@
 	PyObject *idkey;
 	PyObject *data;
 	int id;
-#if TKMAJORMINOR < 8000
-	Tcl_File tfile;
-#endif
+	FHANDLE tfile;
   
 	if (!PyArg_ParseTuple(args, "O", &file))
 		return NULL;
@@ -1207,18 +1218,9 @@
 	PyDict_DelItem(Tkapp_ClientDataDict, idkey);
 	Py_DECREF(idkey);
 
-#if TKMAJORMINOR < 8000
-#ifdef MS_WINDOWS
-	/* We assume this is a socket... */
-	tfile = Tcl_GetFile((ClientData)id, TCL_WIN_SOCKET);
-#else
-	tfile = Tcl_GetFile((ClientData)id, TCL_UNIX_FD);
-#endif
+	tfile = MAKEFHANDLE(id);
 	/* Ought to check for null Tcl_File object... */
 	Tcl_DeleteFileHandler(tfile);
-#else /* >= 8000 */
-	Tcl_DeleteFileHandler(id);
-#endif /* >= 8000 */
 	/* XXX fileHandlerDict */
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -1511,6 +1513,7 @@
 {
 	Tcl_DeleteInterp(Tkapp_Interp(self));
 	PyMem_DEL(self);
+	DisableEventHook();
 }
 
 static PyObject *
@@ -1584,22 +1587,41 @@
 	{NULL,                 NULL}
 };
 
+#ifdef WAIT_FOR_STDIN
+#define WAITFLAG 0
+
+static int stdin_ready = 0;
+
+static void
+MyFileProc(clientData, mask)
+	void *clientData;
+	int mask;
+{
+	stdin_ready = 1;
+}
+#else
+#define WAITFLAG TCL_DONT_WAIT
+#endif
+
 static PyInterpreterState *event_interp = NULL;
 
 static int
 EventHook()
 {
 	PyThreadState *tstate, *save_tstate;
+#ifdef WAIT_FOR_STDIN
+	FHANDLE tfile = MAKEFHANDLE(((int)fileno(stdin)));
 
-	if (Tk_GetNumMainWindows() == 0)
-		return 0;
-	if (event_interp == NULL)
-		return 0;
+	stdin_ready = 0;
+	Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
+#endif
 	tstate = PyThreadState_New(event_interp);
 	save_tstate = PyThreadState_Swap(NULL);
 	PyEval_RestoreThread(tstate);
-	if (!errorInCmd)
-		Tcl_DoOneEvent(TCL_DONT_WAIT);
+#ifdef WAIT_FOR_STDIN
+	while (!errorInCmd && !stdin_ready)
+#endif
+		Tcl_DoOneEvent(WAITFLAG);
 	if (errorInCmd) {
 		errorInCmd = 0;
 		PyErr_Restore(excInCmd, valInCmd, trbInCmd);
@@ -1610,9 +1632,29 @@
 	PyEval_SaveThread();
 	PyThreadState_Swap(save_tstate);
 	PyThreadState_Delete(tstate);
+#ifdef WAIT_FOR_STDIN
+	Tcl_DeleteFileHandler(tfile);
+#endif
 	return 0;
 }
 
+static void
+EnableEventHook()
+{
+	if (PyOS_InputHook == NULL) {
+		event_interp = PyThreadState_Get()->interp;
+		PyOS_InputHook = EventHook;
+	}
+}
+
+static void
+DisableEventHook()
+{
+	if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
+		PyOS_InputHook = NULL;
+	}
+}
+
 
 /* all errors will be checked in one fell swoop in init_tkinter() */
 static void
@@ -1670,11 +1712,6 @@
 	PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
 	PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
 
-	if (PyOS_InputHook == NULL) {
-		event_interp = PyThreadState_Get()->interp;
-		PyOS_InputHook = EventHook;
-	}
-
 	if (PyErr_Occurred())
 		return;