Skip to content

Commit dc91299

Browse files
committed
Merge pull request #1026 from undingen/signal_handling6
Add signal support
2 parents dc49df1 + 28c0c4b commit dc91299

File tree

17 files changed

+300
-53
lines changed

17 files changed

+300
-53
lines changed

from_cpython/Lib/test/test_signal.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# expected: fail
21
import unittest
32
from test import test_support
43
from contextlib import closing
@@ -80,7 +79,8 @@ def run_test(self):
8079
# don't worry about re-setting the default handlers.
8180
signal.signal(signal.SIGHUP, self.handlerA)
8281
signal.signal(signal.SIGUSR1, self.handlerB)
83-
signal.signal(signal.SIGUSR2, signal.SIG_IGN)
82+
# Pyston change: pyston uses SIGUSR2 internally
83+
# signal.signal(signal.SIGUSR2, signal.SIG_IGN)
8484
signal.signal(signal.SIGALRM, signal.default_int_handler)
8585

8686
# Variables the signals will modify:
@@ -117,9 +117,11 @@ def run_test(self):
117117
if test_support.verbose:
118118
print "HandlerBCalled exception caught"
119119

120-
child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
121-
if child:
122-
self.wait(child) # Nothing should happen.
120+
121+
# Pyston change: pyston uses SIGUSR2 internally
122+
# child = ignoring_eintr(subprocess.Popen, ['kill', '-USR2', str(pid)])
123+
# if child:
124+
# self.wait(child) # Nothing should happen.
123125

124126
try:
125127
signal.alarm(1)

from_cpython/Modules/signalmodule.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ initsignal(void)
626626
old_siginthandler = PyOS_setsig(SIGINT, signal_handler);
627627
}
628628

629+
// Pyston change: let the GC scan the handlers
630+
PyGC_AddPotentialRoot(Handlers, sizeof(Handlers));
631+
629632
#ifdef SIGHUP
630633
x = PyInt_FromLong(SIGHUP);
631634
PyDict_SetItemString(d, "SIGHUP", x);
@@ -895,10 +898,6 @@ PyErr_CheckSignals(void)
895898
if (!is_tripped)
896899
return 0;
897900

898-
// Pyston change:
899-
Py_FatalError("TODO");
900-
901-
#if 0
902901
int i;
903902
PyObject *f;
904903

@@ -943,7 +942,6 @@ PyErr_CheckSignals(void)
943942
Py_DECREF(result);
944943
}
945944
}
946-
#endif
947945

948946
return 0;
949947
}

src/codegen/ast_interpreter.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -922,43 +922,66 @@ Value ASTInterpreter::visit_stmt(AST_stmt* node) {
922922
printf("\n");
923923
}
924924

925+
Value rtn;
925926
switch (node->type) {
926927
case AST_TYPE::Assert:
927-
return visit_assert((AST_Assert*)node);
928+
rtn = visit_assert((AST_Assert*)node);
929+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
930+
break;
928931
case AST_TYPE::Assign:
929-
return visit_assign((AST_Assign*)node);
932+
rtn = visit_assign((AST_Assign*)node);
933+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
934+
break;
930935
case AST_TYPE::Delete:
931-
return visit_delete((AST_Delete*)node);
936+
rtn = visit_delete((AST_Delete*)node);
937+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
938+
break;
932939
case AST_TYPE::Exec:
933-
return visit_exec((AST_Exec*)node);
940+
rtn = visit_exec((AST_Exec*)node);
941+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
942+
break;
934943
case AST_TYPE::Expr:
935944
// docstrings are str constant expression statements.
936945
// ignore those while interpreting.
937-
if ((((AST_Expr*)node)->value)->type != AST_TYPE::Str)
938-
return visit_expr((AST_Expr*)node);
946+
if ((((AST_Expr*)node)->value)->type != AST_TYPE::Str) {
947+
rtn = visit_expr((AST_Expr*)node);
948+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
949+
}
939950
break;
940951
case AST_TYPE::Pass:
941-
return Value(); // nothing todo
952+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
953+
break; // nothing todo
942954
case AST_TYPE::Print:
943-
return visit_print((AST_Print*)node);
955+
rtn = visit_print((AST_Print*)node);
956+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
957+
break;
944958
case AST_TYPE::Raise:
945-
return visit_raise((AST_Raise*)node);
959+
rtn = visit_raise((AST_Raise*)node);
960+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
961+
break;
946962
case AST_TYPE::Return:
947-
return visit_return((AST_Return*)node);
963+
rtn = visit_return((AST_Return*)node);
964+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
965+
break;
948966
case AST_TYPE::Global:
949-
return visit_global((AST_Global*)node);
967+
rtn = visit_global((AST_Global*)node);
968+
ASTInterpreterJitInterface::pendingCallsCheckHelper();
969+
break;
950970

951971
// pseudo
952972
case AST_TYPE::Branch:
953-
return visit_branch((AST_Branch*)node);
973+
rtn = visit_branch((AST_Branch*)node);
974+
break;
954975
case AST_TYPE::Jump:
955-
return visit_jump((AST_Jump*)node);
976+
rtn = visit_jump((AST_Jump*)node);
977+
break;
956978
case AST_TYPE::Invoke:
957-
return visit_invoke((AST_Invoke*)node);
979+
rtn = visit_invoke((AST_Invoke*)node);
980+
break;
958981
default:
959982
RELEASE_ASSERT(0, "not implemented");
960983
};
961-
return Value();
984+
return rtn;
962985
}
963986

964987
Value ASTInterpreter::visit_return(AST_Return* node) {
@@ -1652,6 +1675,11 @@ Box* ASTInterpreterJitInterface::landingpadHelper(void* _interpreter) {
16521675
return rtn;
16531676
}
16541677

1678+
void ASTInterpreterJitInterface::pendingCallsCheckHelper() {
1679+
if (unlikely(_pendingcalls_to_do))
1680+
makePendingCalls();
1681+
}
1682+
16551683
Box* ASTInterpreterJitInterface::setExcInfoHelper(void* _interpreter, Box* type, Box* value, Box* traceback) {
16561684
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
16571685
interpreter->getFrameInfo()->exc = ExcInfo(type, value, traceback);

src/codegen/ast_interpreter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct ASTInterpreterJitInterface {
4545
static Box* derefHelper(void* interp, InternedString s);
4646
static Box* doOSRHelper(void* interp, AST_Jump* node);
4747
static Box* landingpadHelper(void* interp);
48+
static void pendingCallsCheckHelper();
4849
static Box* setExcInfoHelper(void* interp, Box* type, Box* value, Box* traceback);
4950
static void setLocalClosureHelper(void* interp, long vreg, InternedString id, Box* v);
5051
static Box* uncacheExcInfoHelper(void* interp);

src/codegen/baseline_jit.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,10 @@ void JitFragmentWriter::emitOSRPoint(AST_Jump* node) {
474474
addAction([=]() { _emitOSRPoint(result, node_var); }, { result, node_var, getInterp() }, ActionType::NORMAL);
475475
}
476476

477+
void JitFragmentWriter::emitPendingCallsCheck() {
478+
call(false, (void*)ASTInterpreterJitInterface::pendingCallsCheckHelper);
479+
}
480+
477481
void JitFragmentWriter::emitPrint(RewriterVar* dest, RewriterVar* var, bool nl) {
478482
if (!dest)
479483
dest = call(false, (void*)getSysStdout);
@@ -696,12 +700,17 @@ RewriterVar* JitFragmentWriter::emitPPCall(void* func_addr, llvm::ArrayRef<Rewri
696700
RewriterVar* obj_cls_var = result->getAttr(offsetof(Box, cls));
697701
addAction([=]() { _emitRecordType(type_recorder_var, obj_cls_var); }, { type_recorder_var, obj_cls_var },
698702
ActionType::NORMAL);
703+
704+
emitPendingCallsCheck();
699705
return result;
700706
}
707+
emitPendingCallsCheck();
701708
return result;
702709
#else
703710
assert(args_vec.size() < 7);
704-
return call(false, func_addr, args_vec);
711+
RewriterVar* result = call(false, func_addr, args_vec);
712+
emitPendingCallsCheck();
713+
return result;
705714
#endif
706715
}
707716

src/codegen/baseline_jit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class JitFragmentWriter : public Rewriter {
246246
void emitExec(RewriterVar* code, RewriterVar* globals, RewriterVar* locals, FutureFlags flags);
247247
void emitJump(CFGBlock* b);
248248
void emitOSRPoint(AST_Jump* node);
249+
void emitPendingCallsCheck();
249250
void emitPrint(RewriterVar* dest, RewriterVar* var, bool nl);
250251
void emitRaise0();
251252
void emitRaise3(RewriterVar* arg0, RewriterVar* arg1, RewriterVar* arg2);

src/codegen/entry.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -378,16 +378,6 @@ static void handle_sigprof_investigate_stattimer(int signum) {
378378
}
379379
#endif
380380

381-
static void handle_sigint(int signum) {
382-
assert(signum == SIGINT);
383-
// TODO: this should set a flag saying a KeyboardInterrupt is pending.
384-
// For now, just call abort(), so that we get a traceback at least.
385-
fprintf(stderr, "SIGINT!\n");
386-
joinRuntime();
387-
Stats::dump(false);
388-
abort();
389-
}
390-
391381
void initCodegen() {
392382
llvm::InitializeNativeTarget();
393383
llvm::InitializeNativeTargetAsmPrinter();
@@ -481,9 +471,8 @@ void initCodegen() {
481471

482472
setupRuntime();
483473

484-
// signal(SIGFPE, &handle_sigfpe);
485-
signal(SIGUSR1, &handle_sigusr1);
486-
signal(SIGINT, &handle_sigint);
474+
// signal(SIGFPE, &handle_sigfpe);
475+
// signal(SIGUSR1, &handle_sigusr1);
487476

488477
#if ENABLE_SAMPLING_PROFILER
489478
struct itimerval prof_timer;

src/codegen/irgen/irgenerator.cpp

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,53 @@ class IREmitterImpl : public IREmitter {
347347
llvm::BasicBlock*& curblock;
348348
IRGenerator* irgenerator;
349349

350+
void emitPendingCallsCheck(llvm::BasicBlock* exc_dest) {
351+
auto&& builder = *getBuilder();
352+
353+
llvm::GlobalVariable* pendingcalls_to_do_gv = g.cur_module->getGlobalVariable("_pendingcalls_to_do");
354+
if (!pendingcalls_to_do_gv) {
355+
static_assert(sizeof(_pendingcalls_to_do) == 4, "");
356+
pendingcalls_to_do_gv = new llvm::GlobalVariable(
357+
*g.cur_module, g.i32, false, llvm::GlobalValue::ExternalLinkage, 0, "_pendingcalls_to_do");
358+
pendingcalls_to_do_gv->setAlignment(4);
359+
}
360+
361+
llvm::BasicBlock* cur_block = builder.GetInsertBlock();
362+
363+
llvm::BasicBlock* pendingcalls_set = createBasicBlock("_pendingcalls_set");
364+
pendingcalls_set->moveAfter(cur_block);
365+
llvm::BasicBlock* join_block = createBasicBlock("continue_after_pendingcalls_check");
366+
join_block->moveAfter(pendingcalls_set);
367+
368+
llvm::Value* pendingcalls_to_do_val = builder.CreateLoad(pendingcalls_to_do_gv, true /* volatile */);
369+
llvm::Value* is_zero
370+
= builder.CreateICmpEQ(pendingcalls_to_do_val, getConstantInt(0, pendingcalls_to_do_val->getType()));
371+
372+
llvm::Metadata* md_vals[]
373+
= { llvm::MDString::get(g.context, "branch_weights"), llvm::ConstantAsMetadata::get(getConstantInt(1000)),
374+
llvm::ConstantAsMetadata::get(getConstantInt(1)) };
375+
llvm::MDNode* branch_weights = llvm::MDNode::get(g.context, llvm::ArrayRef<llvm::Metadata*>(md_vals));
376+
377+
378+
builder.CreateCondBr(is_zero, join_block, pendingcalls_set, branch_weights);
379+
{
380+
setCurrentBasicBlock(pendingcalls_set);
381+
382+
if (exc_dest) {
383+
builder.CreateInvoke(g.funcs.makePendingCalls, join_block, exc_dest);
384+
} else {
385+
builder.CreateCall(g.funcs.makePendingCalls);
386+
builder.CreateBr(join_block);
387+
}
388+
}
389+
390+
cur_block = join_block;
391+
setCurrentBasicBlock(join_block);
392+
}
393+
350394
llvm::CallSite emitCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
351395
ExceptionStyle target_exception_style) {
352-
llvm::Value* stmt = unw_info.current_stmt ? embedRelocatablePtr(unw_info.current_stmt, g.llvm_aststmt_type_ptr)
353-
: getNullPtr(g.llvm_aststmt_type_ptr);
354-
getBuilder()->CreateStore(stmt, irstate->getStmtVar());
396+
emitSetCurrentStmt(unw_info.current_stmt);
355397

356398
if (target_exception_style == CXX && (unw_info.hasHandler() || irstate->getExceptionStyle() == CAPI)) {
357399
// Create the invoke:
@@ -375,9 +417,13 @@ class IREmitterImpl : public IREmitter {
375417
// Normal case:
376418
getBuilder()->SetInsertPoint(normal_dest);
377419
curblock = normal_dest;
420+
emitPendingCallsCheck(exc_dest);
378421
return rtn;
379422
} else {
423+
380424
llvm::CallInst* cs = getBuilder()->CreateCall(callee, args);
425+
if (target_exception_style == CXX)
426+
emitPendingCallsCheck(NULL);
381427
return cs;
382428
}
383429
}
@@ -479,6 +525,15 @@ class IREmitterImpl : public IREmitter {
479525
return llvm::BasicBlock::Create(g.context, name, irstate->getLLVMFunction());
480526
}
481527

528+
// Our current frame introspection approach requires that we update the currently executed stmt before doing a call
529+
// to a function which could throw an exception, inspect the python call frame,...
530+
// Only patchpoint don't need to set the current statement because the stmt will be inluded in the stackmap args.
531+
void emitSetCurrentStmt(AST_stmt* stmt) {
532+
getBuilder()->CreateStore(stmt ? embedRelocatablePtr(stmt, g.llvm_aststmt_type_ptr)
533+
: getNullPtr(g.llvm_aststmt_type_ptr),
534+
irstate->getStmtVar());
535+
}
536+
482537
llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
483538
ExceptionStyle target_exception_style = CXX) override {
484539
#ifndef NDEBUG
@@ -2137,7 +2192,7 @@ class IRGeneratorImpl : public IRGenerator {
21372192

21382193
// Don't call deinitFrame when this is a OSR function because the interpreter will call it
21392194
if (!irstate->getCurFunction()->entry_descriptor)
2140-
emitter.createCall(unw_info, g.funcs.deinitFrame, irstate->getFrameInfoVar());
2195+
emitter.getBuilder()->CreateCall(g.funcs.deinitFrame, irstate->getFrameInfoVar());
21412196

21422197
for (auto& p : symbol_table) {
21432198
p.second->decvref(emitter);
@@ -2878,9 +2933,10 @@ class IRGeneratorImpl : public IRGenerator {
28782933
}
28792934

28802935
void doSafePoint(AST_stmt* next_statement) override {
2881-
// Unwind info is always needed in allowGLReadPreemption if it has any chance of
2882-
// running arbitrary code like finalizers.
2883-
emitter.createCall(UnwindInfo(next_statement, NULL), g.funcs.allowGLReadPreemption);
2936+
// We need to setup frame introspection by updating the current stmt because we can run can run arbitrary code
2937+
// like finalizers inside allowGLReadPreemption.
2938+
emitter.emitSetCurrentStmt(next_statement);
2939+
emitter.getBuilder()->CreateCall(g.funcs.allowGLReadPreemption);
28842940
}
28852941

28862942
// Create a (or reuse an existing) block that will catch a CAPI exception, and then forward
@@ -2902,16 +2958,17 @@ class IRGeneratorImpl : public IRGenerator {
29022958
assert(!phi_node);
29032959
phi_node = emitter.getBuilder()->CreatePHI(g.llvm_aststmt_type_ptr, 0);
29042960

2905-
emitter.createCall(UnwindInfo(current_stmt, NULL), g.funcs.caughtCapiException,
2906-
{ phi_node, embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr) });
2961+
emitter.emitSetCurrentStmt(current_stmt);
2962+
emitter.getBuilder()->CreateCall(g.funcs.caughtCapiException,
2963+
{ phi_node, embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr) });
29072964

29082965
if (!final_dest) {
29092966
// Propagate the exception out of the function:
29102967
if (irstate->getExceptionStyle() == CXX) {
29112968
emitter.getBuilder()->CreateCall(g.funcs.reraiseCapiExcAsCxx);
29122969
emitter.getBuilder()->CreateUnreachable();
29132970
} else {
2914-
emitter.createCall(UnwindInfo(current_stmt, NULL), g.funcs.deinitFrame, irstate->getFrameInfoVar());
2971+
emitter.getBuilder()->CreateCall(g.funcs.deinitFrame, irstate->getFrameInfoVar());
29152972
emitter.getBuilder()->CreateRet(getNullPtr(g.llvm_value_type_ptr));
29162973
}
29172974
} else {

src/codegen/runtime_hooks.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ void initGlobalFuncs(GlobalState& g) {
200200
GET(createSet);
201201
GET(initFrame);
202202
GET(deinitFrame);
203+
GET(makePendingCalls);
203204

204205
GET(getattr);
205206
GET(getattr_capi);

src/codegen/runtime_hooks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct GlobalFuncs {
3434

3535
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *createFunctionFromMetadata, *getFunctionMetadata,
3636
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice,
37-
*createUserClass, *createClosure, *createGenerator, *createSet, *initFrame, *deinitFrame;
37+
*createUserClass, *createClosure, *createGenerator, *createSet, *initFrame, *deinitFrame, *makePendingCalls;
3838
llvm::Value* getattr, *getattr_capi, *setattr, *delattr, *delitem, *delGlobal, *nonzero, *binop, *compare,
3939
*augbinop, *unboxedLen, *getitem, *getitem_capi, *getclsattr, *getGlobal, *setitem, *unaryop, *import,
4040
*importFrom, *importStar, *repr, *exceptionMatches, *yield, *getiterHelper, *hasnext, *setGlobal, *apply_slice;

0 commit comments

Comments
 (0)