@@ -971,3 +971,175 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
971
971
}
972
972
return term_invalid_term ();
973
973
}
974
+
975
+ int context_get_catch_label (Context * ctx , Module * * mod )
976
+ {
977
+ term * ct = ctx -> e ;
978
+ term * last_frame = ctx -> e ;
979
+
980
+ while (ct != ctx -> heap .heap_end ) {
981
+ if (term_is_catch_label (* ct )) {
982
+ int target_module ;
983
+ int target_label = term_to_catch_label_and_module (* ct , & target_module );
984
+ TRACE ("- found catch: label: %i, module: %i\n" , target_label , target_module );
985
+ * mod = globalcontext_get_module_by_index (ctx -> global , target_module );
986
+
987
+ DEBUG_DUMP_STACK (ctx );
988
+ ctx -> e = last_frame ;
989
+ DEBUG_DUMP_STACK (ctx );
990
+
991
+ return target_label ;
992
+
993
+ } else if (term_is_cp (* ct )) {
994
+ last_frame = ct + 1 ;
995
+ }
996
+
997
+ ct ++ ;
998
+ }
999
+
1000
+ return 0 ;
1001
+ }
1002
+
1003
+ COLD_FUNC void context_dump (Context * ctx )
1004
+ {
1005
+ GlobalContext * glb = ctx -> global ;
1006
+
1007
+ fprintf (stderr , "CRASH \n======\n" );
1008
+
1009
+ fprintf (stderr , "pid: " );
1010
+ term_display (stderr , term_from_local_process_id (ctx -> process_id ), ctx );
1011
+ fprintf (stderr , "\n" );
1012
+
1013
+ fprintf (stderr , "\nStacktrace:\n" );
1014
+ term_display (stderr , stacktrace_build (ctx , & ctx -> x [2 ], 3 ), ctx );
1015
+ fprintf (stderr , "\n\n" );
1016
+
1017
+ {
1018
+ Module * cp_mod ;
1019
+ int label ;
1020
+ int offset ;
1021
+ module_cp_to_label_offset (ctx -> cp , & cp_mod , & label , & offset , NULL , ctx -> global );
1022
+ fprintf (stderr , "cp: #CP<module: %i, label: %i, offset: %i>\n\n" ,
1023
+ cp_mod -> module_index , label , offset );
1024
+ }
1025
+
1026
+ fprintf (stderr , "x[0]: " );
1027
+ term_display (stderr , ctx -> x [0 ], ctx );
1028
+ fprintf (stderr , "\nx[1]: " );
1029
+ term_display (stderr , ctx -> x [1 ], ctx );
1030
+ fprintf (stderr , "\nx[2]: " );
1031
+ term_display (stderr , ctx -> x [2 ], ctx );
1032
+ fprintf (stderr , "\n\nStack \n-----\n\n" );
1033
+
1034
+ term * ct = ctx -> e ;
1035
+
1036
+ while (ct != ctx -> heap .heap_end ) {
1037
+ if (term_is_catch_label (* ct )) {
1038
+ int target_module ;
1039
+ int target_label = term_to_catch_label_and_module (* ct , & target_module );
1040
+ fprintf (stderr , "catch: %i:%i\n" , target_label , target_module );
1041
+
1042
+ } else if (term_is_cp (* ct )) {
1043
+ Module * cp_mod ;
1044
+ int label ;
1045
+ int offset ;
1046
+ module_cp_to_label_offset (* ct , & cp_mod , & label , & offset , NULL , ctx -> global );
1047
+ fprintf (stderr , "#CP<module: %i, label: %i, offset: %i>\n" , cp_mod -> module_index , label , offset );
1048
+
1049
+ } else {
1050
+ term_display (stderr , * ct , ctx );
1051
+ fprintf (stderr , "\n" );
1052
+ }
1053
+
1054
+ ct ++ ;
1055
+ }
1056
+
1057
+ fprintf (stderr , "\n\nMailbox\n-------\n" );
1058
+ mailbox_crashdump (ctx );
1059
+
1060
+ fprintf (stderr , "\n\nMonitors\n--------\n" );
1061
+ // Lock processes table to make sure any dying process will not modify monitors
1062
+ struct ListHead * processes_table = synclist_rdlock (& glb -> processes_table );
1063
+ UNUSED (processes_table );
1064
+ struct ListHead * item ;
1065
+ LIST_FOR_EACH (item , & ctx -> monitors_head ) {
1066
+ struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
1067
+ switch (monitor -> monitor_type ) {
1068
+ case CONTEXT_MONITOR_LINK_LOCAL : {
1069
+ struct LinkLocalMonitor * link_monitor = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
1070
+ fprintf (stderr , "link " );
1071
+ if (link_monitor -> unlink_id ) {
1072
+ fprintf (stderr , "(inactive) " );
1073
+ }
1074
+ fprintf (stderr , "to " );
1075
+ term_display (stderr , link_monitor -> link_local_process_id , ctx );
1076
+ fprintf (stderr , "\n" );
1077
+ break ;
1078
+ }
1079
+ case CONTEXT_MONITOR_LINK_REMOTE : {
1080
+ struct LinkRemoteMonitor * link_monitor = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
1081
+ fprintf (stderr , "remote link " );
1082
+ if (link_monitor -> unlink_id ) {
1083
+ fprintf (stderr , "(inactive) " );
1084
+ }
1085
+ fprintf (stderr , "to " );
1086
+ term_display (stderr , link_monitor -> node , ctx );
1087
+ fprintf (stderr , "\n" );
1088
+ break ;
1089
+ }
1090
+ case CONTEXT_MONITOR_MONITORING_LOCAL : {
1091
+ struct MonitorLocalMonitor * monitoring_monitor = CONTAINER_OF (monitor , struct MonitorLocalMonitor , monitor );
1092
+ fprintf (stderr , "monitor to " );
1093
+ term_display (stderr , monitoring_monitor -> monitor_obj , ctx );
1094
+ fprintf (stderr , " ref=%lu" , (long unsigned ) monitoring_monitor -> ref_ticks );
1095
+ fprintf (stderr , "\n" );
1096
+ break ;
1097
+ }
1098
+ case CONTEXT_MONITOR_MONITORED_LOCAL : {
1099
+ struct MonitorLocalMonitor * monitored_monitor = CONTAINER_OF (monitor , struct MonitorLocalMonitor , monitor );
1100
+ fprintf (stderr , "monitored by " );
1101
+ term_display (stderr , monitored_monitor -> monitor_obj , ctx );
1102
+ fprintf (stderr , " ref=%lu" , (long unsigned ) monitored_monitor -> ref_ticks );
1103
+ fprintf (stderr , "\n" );
1104
+ break ;
1105
+ }
1106
+ case CONTEXT_MONITOR_RESOURCE : {
1107
+ struct ResourceContextMonitor * resource_monitor = CONTAINER_OF (monitor , struct ResourceContextMonitor , monitor );
1108
+ fprintf (stderr , "monitored by resource %p ref=%lu" , resource_monitor -> resource_obj , (long unsigned ) resource_monitor -> ref_ticks );
1109
+ fprintf (stderr , "\n" );
1110
+ break ;
1111
+ }
1112
+ }
1113
+ }
1114
+ synclist_unlock (& glb -> processes_table );
1115
+
1116
+ // If crash is caused by out_of_memory, print more data about memory usage
1117
+ if (ctx -> x [0 ] == ERROR_ATOM && ctx -> x [1 ] == OUT_OF_MEMORY_ATOM ) {
1118
+ fprintf (stderr , "\n\nContext memory info\n-------------------\n" );
1119
+ fprintf (stderr , "context_size = %zu\n" , context_size (ctx ));
1120
+ fprintf (stderr , "context_avail_free_memory = %zu\n" , context_avail_free_memory (ctx ));
1121
+ fprintf (stderr , "heap_size = %zu\n" , memory_heap_youngest_size (& ctx -> heap ));
1122
+ fprintf (stderr , "total_heap_size = %zu\n" , memory_heap_memory_size (& ctx -> heap ));
1123
+ fprintf (stderr , "stack_size = %zu\n" , context_stack_size (ctx ));
1124
+ fprintf (stderr , "message_queue_len = %zu\n" , context_message_queue_len (ctx ));
1125
+ fprintf (stderr , "\n\nGlobal memory info\n------------------\n" );
1126
+
1127
+ processes_table = synclist_rdlock (& glb -> processes_table );
1128
+ size_t process_count = 0 ;
1129
+ size_t ports_count = 0 ;
1130
+ LIST_FOR_EACH (item , processes_table ) {
1131
+ Context * p = GET_LIST_ENTRY (item , Context , processes_table_head );
1132
+ process_count ++ ;
1133
+ if (p -> native_handler ) {
1134
+ ports_count ++ ;
1135
+ }
1136
+ }
1137
+ synclist_unlock (& glb -> processes_table );
1138
+
1139
+ fprintf (stderr , "process_count = %zu\n" , process_count );
1140
+ fprintf (stderr , "ports_count = %zu\n" , ports_count );
1141
+ fprintf (stderr , "atoms_count = %zu\n" , atom_table_count (glb -> atom_table ));
1142
+ fprintf (stderr , "refc_binary_total_size = %zu\n" , refc_binary_total_size (ctx ));
1143
+ }
1144
+ fprintf (stderr , "\n\n**End Of Crash Report**\n" );
1145
+ }
0 commit comments