Skip to content

Commit 6dc93d6

Browse files
committed
Retire SystemRestart.
This feature ("experimental" since 2008) has been broken in 2.7.x since 2014. As implemented (when fixed), it still poses technical problems, including an incompatibility with multiple interpreters (sys modules). See Jython-dev.
1 parent ad782a8 commit 6dc93d6

11 files changed

Lines changed: 45 additions & 147 deletions

File tree

Lib/threading.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,6 @@ def __bootstrap(self):
222222
self.run()
223223
except SystemExit:
224224
pass
225-
except InterruptedException:
226-
# Quiet InterruptedExceptions if they're caused by system restart
227-
if not _sys._shouldRestart:
228-
raise
229225
except:
230226
# If sys.stderr is no more (most likely from interpreter
231227
# shutdown) use self.__stderr. Otherwise still use sys (as in

src/org/python/core/FunctionThread.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import java.util.concurrent.atomic.AtomicInteger;
44

5-
import org.python.modules._systemrestart;
6-
75
public class FunctionThread extends Thread
86
{
97
private final PyObject func;
@@ -24,7 +22,7 @@ public void run() {
2422
try {
2523
func.__call__(args);
2624
} catch (PyException exc) {
27-
if (exc.match(Py.SystemExit) || exc.match(_systemrestart.SystemRestart)) {
25+
if (exc.match(Py.SystemExit)) {
2826
return;
2927
}
3028
Py.stderr.println("Unhandled exception in thread started by " + func);

src/org/python/core/PyBaseCode.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55
package org.python.core;
66

7-
import org.python.modules._systemrestart;
87
import com.google.common.base.CharMatcher;
98

109
public abstract class PyBaseCode extends PyCode {
@@ -103,21 +102,16 @@ public PyObject call(ThreadState ts, PyFrame frame, PyObject closure) {
103102
ts.exception = previous_exception;
104103

105104
ts.frame = ts.frame.f_back;
106-
107-
// Check for interruption, which is used for restarting the interpreter
108-
// on Jython
109-
if (ts.getSystemState()._systemRestart && Thread.currentThread().isInterrupted()) {
110-
throw new PyException(_systemrestart.SystemRestart);
111-
}
112105
return ret;
113106
}
114107

115108
public PyObject call(ThreadState state, PyObject globals, PyObject[] defaults,
116109
PyObject closure)
117110
{
118-
if (co_argcount != 0 || varargs || varkwargs)
111+
if (co_argcount != 0 || varargs || varkwargs) {
119112
return call(state, Py.EmptyObjects, Py.NoKeywords, globals, defaults,
120113
closure);
114+
}
121115
PyFrame frame = new PyFrame(this, globals);
122116
if (co_flags.isFlagSet(CodeFlag.CO_GENERATOR)) {
123117
return new PyGenerator(frame, closure);
@@ -128,9 +122,10 @@ public PyObject call(ThreadState state, PyObject globals, PyObject[] defaults,
128122
public PyObject call(ThreadState state, PyObject arg1, PyObject globals, PyObject[] defaults,
129123
PyObject closure)
130124
{
131-
if (co_argcount != 1 || varargs || varkwargs)
125+
if (co_argcount != 1 || varargs || varkwargs) {
132126
return call(state, new PyObject[] {arg1},
133127
Py.NoKeywords, globals, defaults, closure);
128+
}
134129
PyFrame frame = new PyFrame(this, globals);
135130
frame.f_fastlocals[0] = arg1;
136131
if (co_flags.isFlagSet(CodeFlag.CO_GENERATOR)) {
@@ -142,9 +137,10 @@ public PyObject call(ThreadState state, PyObject arg1, PyObject globals, PyObjec
142137
public PyObject call(ThreadState state, PyObject arg1, PyObject arg2, PyObject globals,
143138
PyObject[] defaults, PyObject closure)
144139
{
145-
if (co_argcount != 2 || varargs || varkwargs)
140+
if (co_argcount != 2 || varargs || varkwargs) {
146141
return call(state, new PyObject[] {arg1, arg2},
147142
Py.NoKeywords, globals, defaults, closure);
143+
}
148144
PyFrame frame = new PyFrame(this, globals);
149145
frame.f_fastlocals[0] = arg1;
150146
frame.f_fastlocals[1] = arg2;
@@ -158,9 +154,10 @@ public PyObject call(ThreadState state, PyObject arg1, PyObject arg2, PyObject a
158154
PyObject globals, PyObject[] defaults,
159155
PyObject closure)
160156
{
161-
if (co_argcount != 3 || varargs || varkwargs)
157+
if (co_argcount != 3 || varargs || varkwargs) {
162158
return call(state, new PyObject[] {arg1, arg2, arg3},
163159
Py.NoKeywords, globals, defaults, closure);
160+
}
164161
PyFrame frame = new PyFrame(this, globals);
165162
frame.f_fastlocals[0] = arg1;
166163
frame.f_fastlocals[1] = arg2;
@@ -175,9 +172,10 @@ public PyObject call(ThreadState state, PyObject arg1, PyObject arg2, PyObject a
175172
public PyObject call(ThreadState state, PyObject arg1, PyObject arg2,
176173
PyObject arg3, PyObject arg4, PyObject globals,
177174
PyObject[] defaults, PyObject closure) {
178-
if (co_argcount != 4 || varargs || varkwargs)
175+
if (co_argcount != 4 || varargs || varkwargs) {
179176
return call(state, new PyObject[]{arg1, arg2, arg3, arg4},
180177
Py.NoKeywords, globals, defaults, closure);
178+
}
181179
PyFrame frame = new PyFrame(this, globals);
182180
frame.f_fastlocals[0] = arg1;
183181
frame.f_fastlocals[1] = arg2;

src/org/python/core/PySystemState.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,6 @@ public class PySystemState extends PyObject
188188

189189
private codecs.CodecState codecState;
190190

191-
/** true when a SystemRestart is triggered. */
192-
public boolean _systemRestart = false;
193-
194191
/** Whether bytecode should be written to disk on import. */
195192
public boolean dont_write_bytecode = false;
196193

@@ -1244,18 +1241,6 @@ public static synchronized PySystemState doInitialize(Properties preProperties,
12441241
return Py.defaultSystemState;
12451242
}
12461243

1247-
/**
1248-
* Reset the global static {@code PySytemState} so that a subsequent call to
1249-
* {@link #initialize()} will re-create the state. This is only really necessary in the context
1250-
* of a system restart, but is harmless when shutting down. Using Python after this call is
1251-
* likely to result in an implicit full static initialisation, or fail badly.
1252-
*/
1253-
public static void undoInitialize() {
1254-
Py.defaultSystemState = null;
1255-
registry = null;
1256-
initialized = false;
1257-
}
1258-
12591244
private static PyVersionInfo getVersionInfo() {
12601245
String s;
12611246
if (Version.PY_RELEASE_LEVEL == 0x0A) {

src/org/python/core/PyTableCode.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
* An implementation of PyCode where the actual executable content
66
* is stored as a PyFunctionTable instance and an integer index.
77
*/
8-
9-
import org.python.modules._systemrestart;
10-
118
@Untraversable
129
public class PyTableCode extends PyBaseCode
1310
{
@@ -69,15 +66,18 @@ public PyTableCode(int argcount, String varnames[],
6966
@Override
7067
public PyObject __dir__() {
7168
PyString members[] = new PyString[__members__.length];
72-
for (int i = 0; i < __members__.length; i++)
69+
for (int i = 0; i < __members__.length; i++) {
7370
members[i] = new PyString(__members__[i]);
71+
}
7472
return new PyList(members);
7573
}
7674

7775
private void throwReadonly(String name) {
78-
for (int i = 0; i < __members__.length; i++)
79-
if (__members__[i] == name)
76+
for (int i = 0; i < __members__.length; i++) {
77+
if (__members__[i] == name) {
8078
throw Py.TypeError("readonly attribute");
79+
}
80+
}
8181
throw Py.AttributeError(name);
8282
}
8383

@@ -93,7 +93,9 @@ public void __delattr__(String name) {
9393
}
9494

9595
private static PyTuple toPyStringTuple(String[] ar) {
96-
if (ar == null) return Py.EmptyTuple;
96+
if (ar == null) {
97+
return Py.EmptyTuple;
98+
}
9799
int sz = ar.length;
98100
PyString[] pystr = new PyString[sz];
99101
for (int i = 0; i < sz; i++) {
@@ -207,14 +209,7 @@ public PyObject call(ThreadState ts, PyFrame frame, PyObject closure) {
207209

208210
// Restore previously defined exception
209211
ts.exception = previous_exception;
210-
211212
ts.frame = ts.frame.f_back;
212-
213-
// Check for interruption, which is used for restarting the interpreter
214-
// on Jython
215-
if (ts.getSystemState()._systemRestart && Thread.currentThread().isInterrupted()) {
216-
throw new PyException(_systemrestart.SystemRestart);
217-
}
218213
return ret;
219214
}
220215

src/org/python/modules/Setup.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public class Setup
4141
"_py_compile",
4242
"_random:org.python.modules.random.RandomModule",
4343
"_sre",
44-
"_systemrestart",
4544
"_threading:org.python.modules._threading._threading",
4645
"_weakref:org.python.modules._weakref.WeakrefModule",
4746
"array:org.python.modules.ArrayModule",

src/org/python/modules/_systemrestart.java

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/org/python/modules/thread/thread.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,9 @@ public static FunctionThread _newFunctionThread(PyObject func, PyTuple args) {
6161
}
6262

6363
/**
64-
* Interrupts all running threads spawned by the thread module.
65-
*
66-
* This works in conjunction with:<ul> <li>
67-
* {@link org.python.core.PyTableCode#call}: checks for the interrupted
68-
* status of the current thread and raise a SystemRestart exception if a
69-
* interruption is detected.</li>
70-
* <li>{@link FunctionThread#run()}: exits the current thread when a
71-
* SystemRestart exception is not caught.</li>
72-
*
73-
* Thus, it is possible that this doesn't make all running threads to stop,
74-
* if SystemRestart exception is caught.
64+
* Interrupt all running threads spawned by the thread module. This works in conjunction with:
65+
* {@link org.python.core.PyTableCode#call}, which checks for the interrupted status of the
66+
* current thread, and {@link FunctionThread#run()}, which exits the current thread.
7567
*/
7668
public static void interruptAllThreads() {
7769
group.interrupt();
@@ -92,7 +84,7 @@ public static void exit_thread() {
9284
public static long get_ident() {
9385
return Thread.currentThread().getId();
9486
}
95-
87+
9688
public static long stack_size(PyObject[] args) {
9789
switch (args.length) {
9890
case 0:

src/org/python/util/jython.java

Lines changed: 18 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,13 @@
3030
import org.python.core.PyStringMap;
3131
import org.python.core.PySystemState;
3232
import org.python.core.imp;
33-
import org.python.modules._systemrestart;
3433
import org.python.modules.thread.thread;
3534

3635
public class jython {
3736

3837
/** Exit status: must have {@code OK.ordinal()==0} */
3938
private enum Status {
40-
OK, ERROR, NOT_RUN, SHOULD_RESTART, NO_FILE
39+
OK, ERROR, NOT_RUN, NO_FILE
4140
}
4241

4342
// An instance of this class will provide the console (python.console) by default.
@@ -163,11 +162,14 @@ public static int runJar(String filename) {
163162
return Status.OK.ordinal();
164163
}
165164

166-
public static void main(String[] args) {
167-
Status status;
168-
do {
169-
status = run(args);
170-
} while (status == Status.SHOULD_RESTART);
165+
/** Now equivalent to {@link #main(String[])}, which is to be preferred. */
166+
@Deprecated
167+
public static void run(String[] args) {
168+
main(args);
169+
}
170+
171+
/** Exit Jython with status (converted to an integer). */
172+
private static void exit(Status status) {
171173
System.exit(status.ordinal());
172174
}
173175

@@ -379,20 +381,19 @@ private static void runStartupFile(InteractiveConsole interp) {
379381
* {@code (args)} are arguments to the program.
380382
*
381383
* @param args arguments to the program.
382-
* @return status indicating outcome.
383384
*/
384-
public static Status run(String[] args) {
385+
public static void main(String[] args) {
385386
// Parse the command line options
386387
CommandLineOptions opts = CommandLineOptions.parse(args);
387388
switch (opts.action) {
388389
case VERSION:
389390
System.err.printf("Jython %s\n", Version.PY_VERSION);
390-
return Status.OK;
391+
exit(Status.OK);
391392
case HELP:
392-
return usage(Status.OK);
393+
exit(usage(Status.OK));
393394
case ERROR:
394395
System.err.println(opts.message);
395-
return usage(Status.ERROR);
396+
exit(usage(Status.ERROR));
396397
case RUN:
397398
// Let's run some Python! ...
398399
}
@@ -543,15 +544,10 @@ public static Status run(String[] args) {
543544

544545
} catch (PyException pye) {
545546
// Whatever the mode of execution an uncaught PyException lands here.
546-
if (pye.match(_systemrestart.SystemRestart)) {
547-
// Leave ourselves a note to restart.
548-
sts = Status.SHOULD_RESTART;
549-
} else {
550-
// If pye was SystemExit *and* Options.inspect==false, this will exit the JVM:
551-
Py.printException(pye);
552-
// It was an exception other than SystemExit or Options.inspect==true.
553-
sts = Status.ERROR;
554-
}
547+
// If pye was SystemExit *and* Options.inspect==false, this will exit the JVM:
548+
Py.printException(pye);
549+
// It was an exception other than SystemExit or Options.inspect==true.
550+
sts = Status.ERROR;
555551
}
556552

557553
/*
@@ -581,41 +577,9 @@ public static Status run(String[] args) {
581577
}
582578
}
583579

584-
if (sts == Status.SHOULD_RESTART) {
585-
// Shut down *all* threads and sockets
586-
shutdownInterpreter();
587-
// ..reset the state...
588-
// XXX seems unnecessary given we will call PySystemState.initialize()
589-
// Py.setSystemState(new PySystemState());
590-
// ...and start again
591-
}
592-
593580
// Shut down in a tidy way
594581
interp.cleanup();
595-
PySystemState.undoInitialize();
596-
597-
return sts;
598-
}
599-
600-
/**
601-
* Run any finalizations on the current interpreter in preparation for a SytemRestart.
602-
*/
603-
public static void shutdownInterpreter() {
604-
PySystemState sys = Py.getSystemState();
605-
// Signal to threading.py to modify response to InterruptedException:
606-
sys._systemRestart = true;
607-
// Interrupt (stop?) all the active threads in the jython-threads group.
608-
thread.interruptAllThreads();
609-
// Close all sockets not already covered by Thread.interrupt (e.g. pre-nio sockets)
610-
try {
611-
PyObject socket = sys.modules.__finditem__("socket");
612-
if (socket != null) {
613-
// XXX Fossil code. Raises AttributeError as _closeActiveSockets has been deleted.
614-
socket.__getattr__("_closeActiveSockets").__call__();
615-
}
616-
} catch (PyException pye) {
617-
// don't worry about errors: we're shutting down
618-
}
582+
exit(sts);
619583
}
620584

621585
/**

tests/java/org/python/util/jythonTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class jythonTest {
3535
*/
3636
@Test
3737
public void testDefaultConsole() {
38-
jython.run(commands);
38+
jython.main(commands);
3939
Console console = Py.getConsole();
4040
assertEquals(JLineConsole.class, console.getClass());
4141
}

0 commit comments

Comments
 (0)