1- #include <datadog/crashtracker.h>
21#include <ruby.h>
2+ #include <datadog/crashtracker.h>
33
44#include "datadog_ruby_common.h"
55
6- static VALUE _native_start_or_update_on_fork (int argc , VALUE * argv ,
7- DDTRACE_UNUSED VALUE _self );
6+ static VALUE _native_start_or_update_on_fork (int argc , VALUE * argv , DDTRACE_UNUSED VALUE _self );
87static VALUE _native_stop (DDTRACE_UNUSED VALUE _self );
98
109static bool first_init = true;
@@ -13,36 +12,24 @@ static bool first_init = true;
1312// Once initialized, segfaults will be reported automatically using libdatadog.
1413
1514void crashtracker_init (VALUE core_module ) {
16- VALUE crashtracking_module =
17- rb_define_module_under (core_module , "Crashtracking" );
18- VALUE crashtracker_class =
19- rb_define_class_under (crashtracking_module , "Component" , rb_cObject );
20-
21- rb_define_singleton_method (crashtracker_class ,
22- "_native_start_or_update_on_fork" ,
23- _native_start_or_update_on_fork , -1 );
24- rb_define_singleton_method (crashtracker_class , "_native_stop" , _native_stop ,
25- 0 );
15+ VALUE crashtracking_module = rb_define_module_under (core_module , "Crashtracking" );
16+ VALUE crashtracker_class = rb_define_class_under (crashtracking_module , "Component" , rb_cObject );
17+
18+ rb_define_singleton_method (crashtracker_class , "_native_start_or_update_on_fork" , _native_start_or_update_on_fork , -1 );
19+ rb_define_singleton_method (crashtracker_class , "_native_stop" , _native_stop , 0 );
2620}
2721
28- static VALUE _native_start_or_update_on_fork (int argc , VALUE * argv ,
29- DDTRACE_UNUSED VALUE _self ) {
22+ static VALUE _native_start_or_update_on_fork (int argc , VALUE * argv , DDTRACE_UNUSED VALUE _self ) {
3023 VALUE options ;
3124 rb_scan_args (argc , argv , "0:" , & options );
32- if (options == Qnil )
33- options = rb_hash_new ();
34-
35- VALUE agent_base_url =
36- rb_hash_fetch (options , ID2SYM (rb_intern ("agent_base_url" )));
37- VALUE path_to_crashtracking_receiver_binary = rb_hash_fetch (
38- options , ID2SYM (rb_intern ("path_to_crashtracking_receiver_binary" )));
39- VALUE ld_library_path =
40- rb_hash_fetch (options , ID2SYM (rb_intern ("ld_library_path" )));
41- VALUE tags_as_array =
42- rb_hash_fetch (options , ID2SYM (rb_intern ("tags_as_array" )));
25+ if (options == Qnil ) options = rb_hash_new ();
26+
27+ VALUE agent_base_url = rb_hash_fetch (options , ID2SYM (rb_intern ("agent_base_url" )));
28+ VALUE path_to_crashtracking_receiver_binary = rb_hash_fetch (options , ID2SYM (rb_intern ("path_to_crashtracking_receiver_binary" )));
29+ VALUE ld_library_path = rb_hash_fetch (options , ID2SYM (rb_intern ("ld_library_path" )));
30+ VALUE tags_as_array = rb_hash_fetch (options , ID2SYM (rb_intern ("tags_as_array" )));
4331 VALUE action = rb_hash_fetch (options , ID2SYM (rb_intern ("action" )));
44- VALUE upload_timeout_seconds =
45- rb_hash_fetch (options , ID2SYM (rb_intern ("upload_timeout_seconds" )));
32+ VALUE upload_timeout_seconds = rb_hash_fetch (options , ID2SYM (rb_intern ("upload_timeout_seconds" )));
4633
4734 VALUE start_action = ID2SYM (rb_intern ("start" ));
4835 VALUE update_on_fork_action = ID2SYM (rb_intern ("update_on_fork" ));
@@ -54,75 +41,64 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv,
5441 ENFORCE_TYPE (action , T_SYMBOL );
5542 ENFORCE_TYPE (upload_timeout_seconds , T_FIXNUM );
5643
57- // if (action != start_action && action != update_on_fork_action)
58- // raise_error(eNativeArgumentError, "Unexpected action: %+" PRIsVALUE,
59- // action);
44+ if (action != start_action && action != update_on_fork_action ) rb_raise (rb_eArgError , "Unexpected action: %+" PRIsVALUE , action );
6045
6146 VALUE version = datadog_gem_version ();
6247
63- // Tags and endpoint are heap-allocated, so after here we can't raise
64- // exceptions otherwise we'll leak this memory Start of exception-free zone to
65- // prevent leaks {{
66- ddog_Endpoint * endpoint =
67- ddog_endpoint_from_url (char_slice_from_ruby_string (agent_base_url ));
68- // if (endpoint == NULL) {
69- // raise_error(eNativeRuntimeError,
70- // "Failed to create endpoint from agent_base_url: %" PRIsVALUE,
71- // // agent_base_url);
72- // }
48+ // Tags and endpoint are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
49+ // Start of exception-free zone to prevent leaks {{
50+ ddog_Endpoint * endpoint = ddog_endpoint_from_url (char_slice_from_ruby_string (agent_base_url ));
51+ if (endpoint == NULL ) {
52+ rb_raise (rb_eRuntimeError , "Failed to create endpoint from agent_base_url: %" PRIsVALUE , agent_base_url );
53+ }
7354 ddog_Vec_Tag tags = convert_tags (tags_as_array );
7455
7556 ddog_crasht_Config config = {
76- .additional_files = {},
77- // @ivoanjo: The Ruby VM already uses an alt stack to detect stack
78- // overflows.
79- //
80- // In libdatadog < 14 with `create_alt_stack = true` I saw a segfault,
81- // such as Ruby 2.6's bug with "Process.detach(fork { exit!
82- // }).instance_variable_get(:@foo)" being turned into a
83- // "-e:1:in `instance_variable_get': stack level too deep
84- // (SystemStackError)" by Ruby. The Ruby crash handler also seems to get
85- // confused when this option is enabled and "Process.kill('SEGV',
86- // Process.pid)" gets run.
87- //
88- // This actually changed in libdatadog 14, so I could see no issues with
89- // `create_alt_stack = true`, but not overriding what Ruby set up seems a
90- // saner default to keep anyway.
91- .create_alt_stack = false,
92- .use_alt_stack = true,
93- .endpoint = endpoint ,
94- .resolve_frames =
95- DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER ,
96- .timeout_ms = FIX2INT (upload_timeout_seconds ) * 1000 ,
57+ .additional_files = {},
58+ // @ivoanjo: The Ruby VM already uses an alt stack to detect stack overflows.
59+ //
60+ // In libdatadog < 14 with `create_alt_stack = true` I saw a segfault, such as Ruby 2.6's bug with
61+ // "Process.detach(fork { exit! }).instance_variable_get(:@foo)" being turned into a
62+ // "-e:1:in `instance_variable_get': stack level too deep (SystemStackError)" by Ruby.
63+ // The Ruby crash handler also seems to get confused when this option is enabled and
64+ // "Process.kill('SEGV', Process.pid)" gets run.
65+ //
66+ // This actually changed in libdatadog 14, so I could see no issues with `create_alt_stack = true`, but not
67+ // overriding what Ruby set up seems a saner default to keep anyway.
68+ .create_alt_stack = false,
69+ .use_alt_stack = true,
70+ .endpoint = endpoint ,
71+ .resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER ,
72+ .timeout_ms = FIX2INT (upload_timeout_seconds ) * 1000 ,
9773 };
9874
9975 ddog_crasht_Metadata metadata = {
100- .library_name = DDOG_CHARSLICE_C ("dd-trace-rb" ),
101- .library_version = char_slice_from_ruby_string (version ),
102- .family = DDOG_CHARSLICE_C ("ruby" ),
103- .tags = & tags ,
76+ .library_name = DDOG_CHARSLICE_C ("dd-trace-rb" ),
77+ .library_version = char_slice_from_ruby_string (version ),
78+ .family = DDOG_CHARSLICE_C ("ruby" ),
79+ .tags = & tags ,
10480 };
10581
10682 ddog_crasht_EnvVar ld_library_path_env = {
107- .key = DDOG_CHARSLICE_C ("LD_LIBRARY_PATH" ),
108- .val = char_slice_from_ruby_string (ld_library_path ),
83+ .key = DDOG_CHARSLICE_C ("LD_LIBRARY_PATH" ),
84+ .val = char_slice_from_ruby_string (ld_library_path ),
10985 };
11086
11187 ddog_crasht_ReceiverConfig receiver_config = {
112- .args = {},
113- .env = {.ptr = & ld_library_path_env , .len = 1 },
114- .path_to_receiver_binary =
115- char_slice_from_ruby_string (path_to_crashtracking_receiver_binary ),
116- .optional_stderr_filename = {},
117- .optional_stdout_filename = {},
88+ .args = {},
89+ .env = {.ptr = & ld_library_path_env , .len = 1 },
90+ .path_to_receiver_binary = char_slice_from_ruby_string (path_to_crashtracking_receiver_binary ),
91+ .optional_stderr_filename = {},
92+ .optional_stdout_filename = {},
11893 };
11994
12095 ddog_VoidResult result =
121- action == start_action
122- ? (first_init
123- ? ddog_crasht_init (config , receiver_config , metadata )
124- : ddog_crasht_reconfigure (config , receiver_config , metadata ))
125- : ddog_crasht_update_on_fork (config , receiver_config , metadata );
96+ action == start_action ?
97+ (first_init ?
98+ ddog_crasht_init (config , receiver_config , metadata ) :
99+ ddog_crasht_reconfigure (config , receiver_config , metadata )
100+ ) :
101+ ddog_crasht_update_on_fork (config , receiver_config , metadata );
126102
127103 first_init = false;
128104
@@ -132,9 +108,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv,
132108 // }} End of exception-free zone to prevent leaks
133109
134110 if (result .tag == DDOG_VOID_RESULT_ERR ) {
135- // raise_error(eNativeRuntimeError,
136- // "Failed to start/update the crash tracker: %" PRIsVALUE,
137- // get_error_details_and_drop(&result.err));
111+ rb_raise (rb_eRuntimeError , "Failed to start/update the crash tracker: %" PRIsVALUE , get_error_details_and_drop (& result .err ));
138112 }
139113
140114 return Qtrue ;
@@ -144,9 +118,7 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
144118 ddog_VoidResult result = ddog_crasht_disable ();
145119
146120 if (result .tag == DDOG_VOID_RESULT_ERR ) {
147- // raise_error(eNativeRuntimeError,
148- // "Failed to stop the crash tracker: %" PRIsVALUE,
149- // get_error_details_and_drop(&result.err));
121+ rb_raise (rb_eRuntimeError , "Failed to stop the crash tracker: %" PRIsVALUE , get_error_details_and_drop (& result .err ));
150122 }
151123
152124 return Qtrue ;
0 commit comments