52
52
#define DEFAULT_STACK_SIZE 8
53
53
#define BYTES_PER_TERM (TERM_BITS / 8)
54
54
55
- static struct ResourceContextMonitor * context_monitors_handle_terminate (Context * ctx );
55
+ static struct Monitor * context_monitors_handle_terminate (Context * ctx );
56
56
static void context_distribution_handle_terminate (Context * ctx );
57
57
static void destroy_extended_registers (Context * ctx , unsigned int live );
58
58
@@ -174,6 +174,22 @@ void context_destroy(Context *ctx)
174
174
context_unlink_ack (ctx , immediate_ref_signal -> immediate , immediate_ref_signal -> ref_ticks );
175
175
break ;
176
176
}
177
+ case UnlinkRemoteIDSignal : {
178
+ struct TermSignal * term_signal
179
+ = CONTAINER_OF (signal_message , struct TermSignal , base );
180
+ uint64_t unlink_id = term_maybe_unbox_int64 (term_get_tuple_element (term_signal -> signal_term , 0 ));
181
+ term remote_pid = term_get_tuple_element (term_signal -> signal_term , 1 );
182
+ context_ack_unlink (ctx , remote_pid , unlink_id , true);
183
+ break ;
184
+ }
185
+ case UnlinkRemoteIDAckSignal : {
186
+ struct TermSignal * term_signal
187
+ = CONTAINER_OF (signal_message , struct TermSignal , base );
188
+ uint64_t unlink_id = term_maybe_unbox_int64 (term_get_tuple_element (term_signal -> signal_term , 0 ));
189
+ term remote_pid = term_get_tuple_element (term_signal -> signal_term , 1 );
190
+ context_unlink_ack (ctx , remote_pid , unlink_id );
191
+ break ;
192
+ }
177
193
case DemonitorSignal : {
178
194
struct RefSignal * ref_signal
179
195
= CONTAINER_OF (signal_message , struct RefSignal , base );
@@ -200,24 +216,44 @@ void context_destroy(Context *ctx)
200
216
201
217
// When monitor message is sent, process is no longer in the table
202
218
// and is no longer registered either.
203
- struct ResourceContextMonitor * resource_monitors = context_monitors_handle_terminate (ctx );
219
+ struct Monitor * remaining_monitors = context_monitors_handle_terminate (ctx );
204
220
205
221
synclist_unlock (& ctx -> global -> processes_table );
206
222
207
- // Eventually call resource monitors handlers after the processes table was unlocked
223
+ // Eventually call distribution and resource monitors handlers after the processes table was unlocked
208
224
// The monitors were removed from the list of monitors.
209
- if (resource_monitors ) {
225
+ if (remaining_monitors ) {
210
226
struct ListHead monitors ;
211
- list_prepend (& resource_monitors -> monitor . monitor_list_head , & monitors );
227
+ list_prepend (& remaining_monitors -> monitor_list_head , & monitors );
212
228
213
229
struct ListHead * item ;
214
230
struct ListHead * tmp ;
215
231
MUTABLE_LIST_FOR_EACH (item , tmp , & monitors ) {
216
232
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
217
- struct ResourceContextMonitor * resource_monitor = CONTAINER_OF (monitor , struct ResourceContextMonitor , monitor );
218
- struct RefcBinary * refc = refc_binary_from_data (resource_monitor -> resource_obj );
219
- resource_type_fire_monitor (refc -> resource_type , erl_nif_env_from_context (ctx ), resource_monitor -> resource_obj , ctx -> process_id , resource_monitor -> ref_ticks );
220
- free (monitor );
233
+ switch (monitor -> monitor_type ) {
234
+ case CONTEXT_MONITOR_RESOURCE : {
235
+ struct ResourceContextMonitor * resource_monitor = CONTAINER_OF (monitor , struct ResourceContextMonitor , monitor );
236
+ struct RefcBinary * refc = refc_binary_from_data (resource_monitor -> resource_obj );
237
+ resource_type_fire_monitor (refc -> resource_type , erl_nif_env_from_context (ctx ), resource_monitor -> resource_obj , ctx -> process_id , resource_monitor -> ref_ticks );
238
+ free (monitor );
239
+ break ;
240
+ }
241
+ case CONTEXT_MONITOR_LINK_REMOTE : {
242
+ struct LinkRemoteMonitor * link_monitor = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
243
+ // Handle the case of inactive link.
244
+ if (link_monitor -> unlink_id != UNLINK_ID_LINK_ACTIVE ) {
245
+ free (monitor );
246
+ continue ;
247
+ }
248
+ dist_send_payload_exit (link_monitor , ctx -> exit_reason , ctx );
249
+ free (monitor );
250
+ break ;
251
+ }
252
+ case CONTEXT_MONITOR_LINK_LOCAL :
253
+ case CONTEXT_MONITOR_MONITORED_LOCAL :
254
+ case CONTEXT_MONITOR_MONITORING_LOCAL :
255
+ UNREACHABLE ();
256
+ }
221
257
}
222
258
}
223
259
@@ -430,17 +466,21 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
430
466
break ;
431
467
case LINKS_ATOM : {
432
468
struct ListHead * item ;
433
- size_t links_count = 0 ;
469
+ ret_size = TUPLE_SIZE ( 2 ) ;
434
470
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
435
471
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
436
472
if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
437
473
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
438
474
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
439
- links_count ++ ;
475
+ ret_size += CONS_SIZE ;
476
+ }
477
+ } else if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
478
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
479
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
480
+ ret_size += CONS_SIZE + EXTERNAL_PID_SIZE ;
440
481
}
441
482
}
442
483
}
443
- ret_size = TUPLE_SIZE (2 ) + CONS_SIZE * links_count ;
444
484
break ;
445
485
}
446
486
default :
@@ -522,6 +562,12 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
522
562
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
523
563
list = term_list_prepend (link -> link_local_process_id , list , heap );
524
564
}
565
+ } else if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
566
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
567
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
568
+ term external_pid = term_make_external_process_id (link -> node , link -> pid_number , link -> pid_serial , link -> creation , heap );
569
+ list = term_list_prepend (external_pid , list , heap );
570
+ }
525
571
}
526
572
}
527
573
term_put_tuple_element (ret , 1 , list );
@@ -535,25 +581,24 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
535
581
return true;
536
582
}
537
583
538
- static struct ResourceContextMonitor * context_monitors_handle_terminate (Context * ctx )
584
+ static struct Monitor * context_monitors_handle_terminate (Context * ctx )
539
585
{
540
586
GlobalContext * glb = ctx -> global ;
541
587
struct ListHead * item ;
542
588
struct ListHead * tmp ;
543
- struct ResourceContextMonitor * result = NULL ;
589
+ struct Monitor * result = NULL ;
544
590
MUTABLE_LIST_FOR_EACH (item , tmp , & ctx -> monitors_head ) {
545
591
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
546
592
switch (monitor -> monitor_type ) {
547
593
case CONTEXT_MONITOR_RESOURCE : {
548
594
// monitor with resource
549
595
// remove it from the list we are iterating on and
550
596
// add it to the list of resource monitors to handle afterwards
551
- struct ResourceContextMonitor * resource_monitor = CONTAINER_OF (monitor , struct ResourceContextMonitor , monitor );
552
597
if (result == NULL ) {
553
598
list_init (& monitor -> monitor_list_head );
554
- result = resource_monitor ;
599
+ result = monitor ;
555
600
} else {
556
- list_append (& result -> monitor . monitor_list_head , & monitor -> monitor_list_head );
601
+ list_append (& result -> monitor_list_head , & monitor -> monitor_list_head );
557
602
}
558
603
break ;
559
604
}
@@ -600,6 +645,16 @@ static struct ResourceContextMonitor *context_monitors_handle_terminate(Context
600
645
free (monitor );
601
646
break ;
602
647
}
648
+ case CONTEXT_MONITOR_LINK_REMOTE : {
649
+ // Process it afterwards
650
+ if (result == NULL ) {
651
+ list_init (& monitor -> monitor_list_head );
652
+ result = monitor ;
653
+ } else {
654
+ list_append (& result -> monitor_list_head , & monitor -> monitor_list_head );
655
+ }
656
+ break ;
657
+ }
603
658
case CONTEXT_MONITOR_MONITORED_LOCAL : {
604
659
struct MonitorLocalMonitor * monitored_monitor = CONTAINER_OF (monitor , struct MonitorLocalMonitor , monitor );
605
660
int32_t local_process_id = term_to_local_process_id (monitored_monitor -> monitor_obj );
@@ -647,15 +702,28 @@ static void context_distribution_handle_terminate(Context *ctx)
647
702
648
703
struct Monitor * monitor_link_new (term link_pid )
649
704
{
650
- struct LinkLocalMonitor * monitor = malloc (sizeof (struct LinkLocalMonitor ));
651
- if (IS_NULL_PTR (monitor )) {
652
- return NULL ;
705
+ if (term_is_local_pid_or_port (link_pid )) {
706
+ struct LinkLocalMonitor * monitor = malloc (sizeof (struct LinkLocalMonitor ));
707
+ if (IS_NULL_PTR (monitor )) {
708
+ return NULL ;
709
+ }
710
+ monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_LOCAL ;
711
+ monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
712
+ monitor -> link_local_process_id = link_pid ;
713
+ return & monitor -> monitor ;
714
+ } else {
715
+ struct LinkRemoteMonitor * monitor = malloc (sizeof (struct LinkRemoteMonitor ));
716
+ if (IS_NULL_PTR (monitor )) {
717
+ return NULL ;
718
+ }
719
+ monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_REMOTE ;
720
+ monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
721
+ monitor -> node = term_get_external_node (link_pid );
722
+ monitor -> pid_number = term_get_external_pid_process_id (link_pid );
723
+ monitor -> pid_serial = term_get_external_pid_serial (link_pid );
724
+ monitor -> creation = term_get_external_node_creation (link_pid );
725
+ return & monitor -> monitor ;
653
726
}
654
- monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_LOCAL ;
655
- monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
656
- monitor -> link_local_process_id = link_pid ;
657
-
658
- return & monitor -> monitor ;
659
727
}
660
728
661
729
struct Monitor * monitor_new (term monitor_pid , uint64_t ref_ticks , bool is_monitoring )
@@ -723,6 +791,18 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
723
791
}
724
792
break ;
725
793
}
794
+ case CONTEXT_MONITOR_LINK_REMOTE : {
795
+ struct LinkRemoteMonitor * new_link_monitor = CONTAINER_OF (new_monitor , struct LinkRemoteMonitor , monitor );
796
+ struct LinkRemoteMonitor * existing_link_monitor = CONTAINER_OF (existing , struct LinkRemoteMonitor , monitor );
797
+ if (UNLIKELY (existing_link_monitor -> node == new_link_monitor -> node
798
+ && existing_link_monitor -> pid_number == new_link_monitor -> pid_number
799
+ && existing_link_monitor -> pid_serial == new_link_monitor -> pid_serial
800
+ && existing_link_monitor -> creation == new_link_monitor -> creation )) {
801
+ free (new_monitor );
802
+ return false;
803
+ }
804
+ break ;
805
+ }
726
806
}
727
807
}
728
808
}
@@ -735,7 +815,7 @@ bool context_set_unlink_id(Context *ctx, term link_pid, uint64_t *unlink_id)
735
815
struct ListHead * item ;
736
816
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
737
817
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
738
- if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
818
+ if (term_is_local_pid_or_port ( link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
739
819
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
740
820
if (link -> link_local_process_id == link_pid ) {
741
821
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
@@ -747,6 +827,21 @@ bool context_set_unlink_id(Context *ctx, term link_pid, uint64_t *unlink_id)
747
827
return false;
748
828
}
749
829
}
830
+ } else if (term_is_external_pid (link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
831
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
832
+ if (link -> node == term_get_external_node (link_pid )
833
+ && link -> pid_number == term_get_external_pid_process_id (link_pid )
834
+ && link -> pid_serial == term_get_external_pid_serial (link_pid )
835
+ && link -> creation == term_get_external_node_creation (link_pid )) {
836
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
837
+ uint64_t new_id = globalcontext_get_ref_ticks (ctx -> global );
838
+ link -> unlink_id = new_id ;
839
+ * unlink_id = new_id ;
840
+ return true;
841
+ } else {
842
+ return false;
843
+ }
844
+ }
750
845
}
751
846
}
752
847
return false;
@@ -757,7 +852,7 @@ void context_ack_unlink(Context *ctx, term link_pid, uint64_t unlink_id, bool pr
757
852
struct ListHead * item ;
758
853
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
759
854
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
760
- if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
855
+ if (term_is_local_pid_or_port ( link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
761
856
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
762
857
if (link -> link_local_process_id == link_pid ) {
763
858
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
@@ -786,6 +881,20 @@ void context_ack_unlink(Context *ctx, term link_pid, uint64_t unlink_id, bool pr
786
881
}
787
882
return ;
788
883
}
884
+ } else if (term_is_external_pid (link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
885
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
886
+ if (link -> node == term_get_external_node (link_pid )
887
+ && link -> pid_number == term_get_external_pid_process_id (link_pid )
888
+ && link -> pid_serial == term_get_external_pid_serial (link_pid )
889
+ && link -> creation == term_get_external_node_creation (link_pid )) {
890
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
891
+ // Send ack and remove link
892
+ dist_send_unlink_id_ack (unlink_id , term_from_local_process_id (ctx -> process_id ), link_pid , ctx );
893
+ list_remove (& monitor -> monitor_list_head );
894
+ free (monitor );
895
+ }
896
+ return ;
897
+ }
789
898
}
790
899
}
791
900
}
@@ -834,6 +943,7 @@ void context_demonitor(Context *ctx, uint64_t ref_ticks)
834
943
}
835
944
}
836
945
case CONTEXT_MONITOR_LINK_LOCAL :
946
+ case CONTEXT_MONITOR_LINK_REMOTE :
837
947
break ;
838
948
}
839
949
}
@@ -855,6 +965,7 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
855
965
break ;
856
966
}
857
967
case CONTEXT_MONITOR_LINK_LOCAL :
968
+ case CONTEXT_MONITOR_LINK_REMOTE :
858
969
case CONTEXT_MONITOR_RESOURCE :
859
970
break ;
860
971
}
0 commit comments