Skip to content

Commit 5b26abb

Browse files
committed
Gracefully delay runtime error up to 1s. Add .willdispatch().
1 parent 276a8f3 commit 5b26abb

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

Lib/pydoc.py

+1
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,7 @@ def __init__(self, window, port=7464):
19191919
self.expanded = 0
19201920
self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight))
19211921
self.window.wm_minsize(self.minwidth, self.minheight)
1922+
self.window.tk.willdispatch()
19221923

19231924
import threading
19241925
threading.Thread(

Modules/_tkinter.c

+31-12
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,24 @@ Sleep(int milli)
310310
#endif /* MS_WINDOWS */
311311
#endif /* WITH_THREAD */
312312

313+
/* Wait up to 1s for the mainloop to come up. */
314+
315+
static int
316+
WaitForMainloop(TkappObject* self)
317+
{
318+
int i;
319+
for (i = 0; i < 10; i++) {
320+
if (self->dispatching)
321+
return 1;
322+
Py_BEGIN_ALLOW_THREADS
323+
Sleep(100);
324+
Py_END_ALLOW_THREADS
325+
}
326+
if (self->dispatching)
327+
return 1;
328+
PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
329+
return 0;
330+
}
313331

314332

315333
static char *
@@ -1138,11 +1156,8 @@ Tkapp_Call(PyObject *_self, PyObject *args)
11381156
marshal the parameters to the interpreter thread. */
11391157
Tkapp_CallEvent *ev;
11401158
PyObject *exc_type, *exc_value, *exc_tb;
1141-
if (!self->dispatching) {
1142-
PyErr_SetString(PyExc_RuntimeError,
1143-
"main thread is not in main loop");
1159+
if (!WaitForMainloop(self))
11441160
return NULL;
1145-
}
11461161
ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
11471162
ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
11481163
ev->self = self;
@@ -1427,11 +1442,8 @@ var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
14271442
the call to the interpreter thread, then wait for
14281443
completion. */
14291444

1430-
if (!self->dispatching) {
1431-
PyErr_SetString(PyExc_RuntimeError,
1432-
"main thread is not in main loop");
1445+
if (!WaitForMainloop(self))
14331446
return NULL;
1434-
}
14351447
ev->cond = NULL;
14361448
ev->ev.proc = (Tcl_EventProc*)var_proc;
14371449
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
@@ -1943,11 +1955,8 @@ Tkapp_CreateCommand(PyObject *_self, PyObject *args)
19431955
}
19441956

19451957
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
1946-
!self->dispatching) {
1947-
PyErr_SetString(PyExc_RuntimeError,
1948-
"main thread is not in main loop");
1958+
!WaitForMainloop(self))
19491959
return NULL;
1950-
}
19511960

19521961
data = PyMem_NEW(PythonCmd_ClientData, 1);
19531962
if (!data)
@@ -2423,12 +2432,22 @@ Tkapp_WantObjects(PyObject *self, PyObject *args)
24232432
return Py_None;
24242433
}
24252434

2435+
static PyObject *
2436+
Tkapp_WillDispatch(PyObject *self, PyObject *args)
2437+
{
2438+
2439+
((TkappObject*)self)->dispatching = 1;
2440+
2441+
Py_INCREF(Py_None);
2442+
return Py_None;
2443+
}
24262444

24272445

24282446
/**** Tkapp Method List ****/
24292447

24302448
static PyMethodDef Tkapp_methods[] =
24312449
{
2450+
{"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
24322451
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
24332452
{"call", Tkapp_Call, METH_OLDARGS},
24342453
{"globalcall", Tkapp_GlobalCall, METH_OLDARGS},

0 commit comments

Comments
 (0)