Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion python/src/main/resources/python/zeppelin_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@
# limitations under the License.
#

import os, sys, traceback, json, re
import os, signal, sys, traceback, json, re

from py4j.java_gateway import java_import, JavaGateway, GatewayClient
from py4j.protocol import Py4JJavaError

import ast

# When Zeppelin is started via zeppelin-daemon.sh (nohup ... &), this process
# inherits SIGINT=SIG_IGN and CPython keeps it ignored instead of installing the
# KeyboardInterrupt handler, so PythonInterpreter.cancel()'s SIGINT would be a
# no-op. Restore the default handler to keep paragraph cancellation working.
if signal.getsignal(signal.SIGINT) == signal.SIG_IGN:
signal.signal(signal.SIGINT, signal.default_int_handler)

class Logger(object):
def __init__(self):
pass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterGroup;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResultMessage;
import org.apache.zeppelin.interpreter.LazyOpenInterpreter;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -35,8 +36,12 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -174,4 +179,42 @@ public void testFailtoLaunchPythonProcess() throws InterpreterException {
assertTrue(stacktrace.contains("No such file or directory"), stacktrace);
}
}

@Test
public void testSigintDefaultHandlerRestoredWhenInheritedIgnored()
throws IOException, InterpreterException {
tearDown();

File wrapper = File.createTempFile("python-sigint-wrapper", ".sh");
wrapper.deleteOnExit();
Files.write(wrapper.toPath(), Arrays.asList(
"#!/bin/sh",
"trap '' INT",
"exec python \"$@\""));
wrapper.setExecutable(true);

intpGroup = new InterpreterGroup();

Properties properties = new Properties();
properties.setProperty("zeppelin.python", wrapper.getAbsolutePath());
properties.setProperty("zeppelin.python.useIPython", "false");
properties.setProperty("zeppelin.python.gatewayserver_address", "127.0.0.1");

interpreter = new LazyOpenInterpreter(new PythonInterpreter(properties));

intpGroup.put("note", new LinkedList<Interpreter>());
intpGroup.get("note").add(interpreter);
interpreter.setInterpreterGroup(intpGroup);

InterpreterContext.set(getInterpreterContext());

InterpreterContext context = getInterpreterContext();
InterpreterResult result = interpreter.interpret(
"import signal\nprint(signal.getsignal(signal.SIGINT))", context);
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
List<InterpreterResultMessage> interpreterResultMessages =
context.out.toInterpreterResultMessage();
String output = interpreterResultMessages.get(0).getData();
assertTrue(output.contains("default_int_handler"), output);
}
}
Loading