@@ -1062,6 +1062,66 @@ class RetainedCollector : public BaseCollector {
1062
1062
}
1063
1063
};
1064
1064
1065
+ class GlobalSignalHandler {
1066
+ static LiveSample *live_sample;
1067
+
1068
+ public:
1069
+ static GlobalSignalHandler *get_instance () {
1070
+ static GlobalSignalHandler instance;
1071
+ return &instance;
1072
+ }
1073
+
1074
+ void install () {
1075
+ const std::lock_guard<std::mutex> lock (mutex);
1076
+ count++;
1077
+
1078
+ if (count == 1 ) setup_signal_handler ();
1079
+ }
1080
+
1081
+ void uninstall () {
1082
+ const std::lock_guard<std::mutex> lock (mutex);
1083
+ count--;
1084
+
1085
+ if (count == 0 ) clear_signal_handler ();
1086
+ }
1087
+
1088
+ void record_sample (LiveSample &sample, pthread_t pthread_id) {
1089
+ const std::lock_guard<std::mutex> lock (mutex);
1090
+
1091
+ live_sample = &sample;
1092
+ if (pthread_kill (pthread_id, SIGPROF)) {
1093
+ rb_bug (" pthread_kill failed" );
1094
+ }
1095
+ sample.wait ();
1096
+ live_sample = NULL ;
1097
+ }
1098
+
1099
+ private:
1100
+ std::mutex mutex;
1101
+ int count;
1102
+
1103
+ static void signal_handler (int sig, siginfo_t * sinfo, void * ucontext) {
1104
+ assert (live_sample);
1105
+ live_sample->sample_current_thread ();
1106
+ }
1107
+
1108
+ void setup_signal_handler () {
1109
+ struct sigaction sa;
1110
+ sa.sa_sigaction = signal_handler;
1111
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
1112
+ sigemptyset (&sa.sa_mask );
1113
+ sigaction (SIGPROF, &sa, NULL );
1114
+ }
1115
+
1116
+ void clear_signal_handler () {
1117
+ struct sigaction sa;
1118
+ sa.sa_handler = SIG_IGN;
1119
+ sa.sa_flags = SA_RESTART;
1120
+ sigemptyset (&sa.sa_mask );
1121
+ sigaction (SIGPROF, &sa, NULL );
1122
+ }
1123
+ };
1124
+ LiveSample *GlobalSignalHandler::live_sample;
1065
1125
1066
1126
class TimeCollector : public BaseCollector {
1067
1127
MarkerTable markers;
@@ -1072,8 +1132,6 @@ class TimeCollector : public BaseCollector {
1072
1132
atomic_bool running;
1073
1133
SamplerSemaphore thread_stopped;
1074
1134
1075
- static LiveSample *live_sample;
1076
-
1077
1135
TimeStamp interval;
1078
1136
1079
1137
public:
@@ -1094,11 +1152,6 @@ class TimeCollector : public BaseCollector {
1094
1152
}
1095
1153
}
1096
1154
1097
- static void signal_handler (int sig, siginfo_t * sinfo, void * ucontext) {
1098
- assert (live_sample);
1099
- live_sample->sample_current_thread ();
1100
- }
1101
-
1102
1155
VALUE get_markers () {
1103
1156
VALUE list = rb_ary_new2 (this ->markers .list .size ());
1104
1157
@@ -1111,7 +1164,6 @@ class TimeCollector : public BaseCollector {
1111
1164
1112
1165
void sample_thread_run () {
1113
1166
LiveSample sample;
1114
- live_sample = &sample;
1115
1167
1116
1168
TimeStamp next_sample_schedule = TimeStamp::Now ();
1117
1169
while (running) {
@@ -1121,10 +1173,7 @@ class TimeCollector : public BaseCollector {
1121
1173
for (auto &thread : threads.list ) {
1122
1174
// if (thread.state == Thread::State::RUNNING) {
1123
1175
if (thread.state == Thread::State::RUNNING || (thread.state == Thread::State::SUSPENDED && thread.stack_on_suspend .size () == 0 )) {
1124
- if (pthread_kill (thread.pthread_id , SIGPROF)) {
1125
- rb_bug (" pthread_kill failed" );
1126
- }
1127
- sample.wait ();
1176
+ GlobalSignalHandler::get_instance ()->record_sample (sample, thread.pthread_id );
1128
1177
1129
1178
if (sample.sample .gc ) {
1130
1179
// fprintf(stderr, "skipping GC sample\n");
@@ -1151,8 +1200,6 @@ class TimeCollector : public BaseCollector {
1151
1200
TimeStamp::Sleep (sleep_time);
1152
1201
}
1153
1202
1154
- live_sample = NULL ;
1155
-
1156
1203
thread_stopped.post ();
1157
1204
}
1158
1205
@@ -1222,11 +1269,7 @@ class TimeCollector : public BaseCollector {
1222
1269
return false ;
1223
1270
}
1224
1271
1225
- struct sigaction sa;
1226
- sa.sa_sigaction = signal_handler;
1227
- sa.sa_flags = SA_RESTART | SA_SIGINFO;
1228
- sigemptyset (&sa.sa_mask );
1229
- sigaction (SIGPROF, &sa, NULL );
1272
+ GlobalSignalHandler::get_instance ()->install ();
1230
1273
1231
1274
running = true ;
1232
1275
@@ -1256,11 +1299,7 @@ class TimeCollector : public BaseCollector {
1256
1299
running = false ;
1257
1300
thread_stopped.wait ();
1258
1301
1259
- struct sigaction sa;
1260
- sa.sa_handler = SIG_IGN;
1261
- sa.sa_flags = SA_RESTART;
1262
- sigemptyset (&sa.sa_mask );
1263
- sigaction (SIGPROF, &sa, NULL );
1302
+ GlobalSignalHandler::get_instance ()->uninstall ();
1264
1303
1265
1304
rb_internal_thread_remove_event_hook (thread_hook);
1266
1305
rb_remove_event_hook (internal_gc_event_cb);
@@ -1318,8 +1357,6 @@ class TimeCollector : public BaseCollector {
1318
1357
}
1319
1358
};
1320
1359
1321
- LiveSample *TimeCollector::live_sample;
1322
-
1323
1360
static void
1324
1361
collector_mark (void *data) {
1325
1362
BaseCollector *collector = static_cast <BaseCollector *>(data);
0 commit comments