forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
signal-handling.c
135 lines (117 loc) · 3.23 KB
/
signal-handling.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// This file is a part of Julia. License is MIT: http:https://julialang.org/license
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "julia.h"
#include "julia_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <threading.h>
// Profiler control variables //
static volatile intptr_t *bt_data_prof = NULL;
static volatile size_t bt_size_max = 0;
static volatile size_t bt_size_cur = 0;
static volatile uint64_t nsecprof = 0;
static volatile int running = 0;
static const uint64_t GIGA = 1000000000ULL;
// Timers to take samples at intervals
JL_DLLEXPORT void jl_profile_stop_timer(void);
JL_DLLEXPORT int jl_profile_start_timer(void);
static uint64_t jl_last_sigint_trigger = 0;
static void jl_clear_force_sigint(void)
{
jl_last_sigint_trigger = 0;
}
static int jl_check_force_sigint(void)
{
static double accum_weight = 0;
uint64_t cur_time = uv_hrtime();
uint64_t dt = cur_time - jl_last_sigint_trigger;
uint64_t last_t = jl_last_sigint_trigger;
jl_last_sigint_trigger = cur_time;
if (last_t == 0) {
accum_weight = 0;
return 0;
}
double new_weight = accum_weight * exp(-(dt / 1e9)) + 0.3;
if (!isnormal(new_weight))
new_weight = 0;
accum_weight = new_weight;
return new_weight > 1;
}
static int exit_on_sigint = 0;
JL_DLLEXPORT void jl_exit_on_sigint(int on)
{
exit_on_sigint = on;
}
// what to do on SIGINT
JL_DLLEXPORT void jl_sigint_action(void)
{
if (exit_on_sigint) jl_exit(130); // 128+SIGINT
jl_throw(jl_interrupt_exception);
}
#if defined(_WIN32)
#include "signals-win.c"
#else
#include "signals-unix.c"
#endif
// what to do on a critical error
void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_t *bt_size)
{
// This function is not allowed to reference any TLS variables.
// We need to explicitly pass in the TLS buffer pointer when
// we make `jl_filename` and `jl_lineno` thread local.
size_t i, n = *bt_size;
if (sig)
jl_safe_printf("\nsignal (%d): %s\n", sig, strsignal(sig));
jl_safe_printf("while loading %s, in expression starting on line %d\n", jl_filename, jl_lineno);
if (context)
*bt_size = n = rec_backtrace_ctx(bt_data, JL_MAX_BT_SIZE, context);
for (i = 0; i < n; i++)
jl_gdblookup(bt_data[i] - 1);
gc_debug_print_status();
gc_debug_critical_error();
}
///////////////////////
// Utility functions //
///////////////////////
JL_DLLEXPORT int jl_profile_init(size_t maxsize, uint64_t delay_nsec)
{
bt_size_max = maxsize;
nsecprof = delay_nsec;
if (bt_data_prof != NULL)
free((void*)bt_data_prof);
bt_data_prof = (intptr_t*) calloc(maxsize, sizeof(intptr_t));
if (bt_data_prof == NULL && maxsize > 0)
return -1;
bt_size_cur = 0;
return 0;
}
JL_DLLEXPORT uint8_t *jl_profile_get_data(void)
{
return (uint8_t*) bt_data_prof;
}
JL_DLLEXPORT size_t jl_profile_len_data(void)
{
return bt_size_cur;
}
JL_DLLEXPORT size_t jl_profile_maxlen_data(void)
{
return bt_size_max;
}
JL_DLLEXPORT uint64_t jl_profile_delay_nsec(void)
{
return nsecprof;
}
JL_DLLEXPORT void jl_profile_clear_data(void)
{
bt_size_cur = 0;
}
JL_DLLEXPORT int jl_profile_is_running(void)
{
return running;
}
#ifdef __cplusplus
}
#endif