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
@@ -439,17 +475,21 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
439
475
break ;
440
476
case LINKS_ATOM : {
441
477
struct ListHead * item ;
442
- size_t links_count = 0 ;
478
+ ret_size = TUPLE_SIZE ( 2 ) ;
443
479
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
444
480
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
445
481
if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
446
482
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
447
483
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
448
- links_count ++ ;
484
+ ret_size += CONS_SIZE ;
485
+ }
486
+ } else if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
487
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
488
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
489
+ ret_size += CONS_SIZE + EXTERNAL_PID_SIZE ;
449
490
}
450
491
}
451
492
}
452
- ret_size = TUPLE_SIZE (2 ) + CONS_SIZE * links_count ;
453
493
break ;
454
494
}
455
495
default :
@@ -531,6 +571,12 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
531
571
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
532
572
list = term_list_prepend (link -> link_local_process_id , list , heap );
533
573
}
574
+ } else if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
575
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
576
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
577
+ term external_pid = term_make_external_process_id (link -> node , link -> pid_number , link -> pid_serial , link -> creation , heap );
578
+ list = term_list_prepend (external_pid , list , heap );
579
+ }
534
580
}
535
581
}
536
582
term_put_tuple_element (ret , 1 , list );
@@ -544,25 +590,24 @@ bool context_get_process_info(Context *ctx, term *out, size_t *term_size, term a
544
590
return true;
545
591
}
546
592
547
- static struct ResourceContextMonitor * context_monitors_handle_terminate (Context * ctx )
593
+ static struct Monitor * context_monitors_handle_terminate (Context * ctx )
548
594
{
549
595
GlobalContext * glb = ctx -> global ;
550
596
struct ListHead * item ;
551
597
struct ListHead * tmp ;
552
- struct ResourceContextMonitor * result = NULL ;
598
+ struct Monitor * result = NULL ;
553
599
MUTABLE_LIST_FOR_EACH (item , tmp , & ctx -> monitors_head ) {
554
600
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
555
601
switch (monitor -> monitor_type ) {
556
602
case CONTEXT_MONITOR_RESOURCE : {
557
603
// monitor with resource
558
604
// remove it from the list we are iterating on and
559
605
// add it to the list of resource monitors to handle afterwards
560
- struct ResourceContextMonitor * resource_monitor = CONTAINER_OF (monitor , struct ResourceContextMonitor , monitor );
561
606
if (result == NULL ) {
562
607
list_init (& monitor -> monitor_list_head );
563
- result = resource_monitor ;
608
+ result = monitor ;
564
609
} else {
565
- list_append (& result -> monitor . monitor_list_head , & monitor -> monitor_list_head );
610
+ list_append (& result -> monitor_list_head , & monitor -> monitor_list_head );
566
611
}
567
612
break ;
568
613
}
@@ -605,6 +650,16 @@ static struct ResourceContextMonitor *context_monitors_handle_terminate(Context
605
650
free (monitor );
606
651
break ;
607
652
}
653
+ case CONTEXT_MONITOR_LINK_REMOTE : {
654
+ // Process it afterwards
655
+ if (result == NULL ) {
656
+ list_init (& monitor -> monitor_list_head );
657
+ result = monitor ;
658
+ } else {
659
+ list_append (& result -> monitor_list_head , & monitor -> monitor_list_head );
660
+ }
661
+ break ;
662
+ }
608
663
case CONTEXT_MONITOR_MONITORED_LOCAL : {
609
664
struct MonitorLocalMonitor * monitored_monitor = CONTAINER_OF (monitor , struct MonitorLocalMonitor , monitor );
610
665
int32_t local_process_id = term_to_local_process_id (monitored_monitor -> monitor_obj );
@@ -651,15 +706,28 @@ static void context_distribution_handle_terminate(Context *ctx)
651
706
652
707
struct Monitor * monitor_link_new (term link_pid )
653
708
{
654
- struct LinkLocalMonitor * monitor = malloc (sizeof (struct LinkLocalMonitor ));
655
- if (IS_NULL_PTR (monitor )) {
656
- return NULL ;
709
+ if (term_is_local_pid_or_port (link_pid )) {
710
+ struct LinkLocalMonitor * monitor = malloc (sizeof (struct LinkLocalMonitor ));
711
+ if (IS_NULL_PTR (monitor )) {
712
+ return NULL ;
713
+ }
714
+ monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_LOCAL ;
715
+ monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
716
+ monitor -> link_local_process_id = link_pid ;
717
+ return & monitor -> monitor ;
718
+ } else {
719
+ struct LinkRemoteMonitor * monitor = malloc (sizeof (struct LinkRemoteMonitor ));
720
+ if (IS_NULL_PTR (monitor )) {
721
+ return NULL ;
722
+ }
723
+ monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_REMOTE ;
724
+ monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
725
+ monitor -> node = term_get_external_node (link_pid );
726
+ monitor -> pid_number = term_get_external_pid_process_id (link_pid );
727
+ monitor -> pid_serial = term_get_external_pid_serial (link_pid );
728
+ monitor -> creation = term_get_external_node_creation (link_pid );
729
+ return & monitor -> monitor ;
657
730
}
658
- monitor -> monitor .monitor_type = CONTEXT_MONITOR_LINK_LOCAL ;
659
- monitor -> unlink_id = UNLINK_ID_LINK_ACTIVE ;
660
- monitor -> link_local_process_id = link_pid ;
661
-
662
- return & monitor -> monitor ;
663
731
}
664
732
665
733
struct Monitor * monitor_new (term monitor_pid , uint64_t ref_ticks , bool is_monitoring )
@@ -727,6 +795,18 @@ bool context_add_monitor(Context *ctx, struct Monitor *new_monitor)
727
795
}
728
796
break ;
729
797
}
798
+ case CONTEXT_MONITOR_LINK_REMOTE : {
799
+ struct LinkRemoteMonitor * new_link_monitor = CONTAINER_OF (new_monitor , struct LinkRemoteMonitor , monitor );
800
+ struct LinkRemoteMonitor * existing_link_monitor = CONTAINER_OF (existing , struct LinkRemoteMonitor , monitor );
801
+ if (UNLIKELY (existing_link_monitor -> node == new_link_monitor -> node
802
+ && existing_link_monitor -> pid_number == new_link_monitor -> pid_number
803
+ && existing_link_monitor -> pid_serial == new_link_monitor -> pid_serial
804
+ && existing_link_monitor -> creation == new_link_monitor -> creation )) {
805
+ free (new_monitor );
806
+ return false;
807
+ }
808
+ break ;
809
+ }
730
810
}
731
811
}
732
812
}
@@ -739,7 +819,7 @@ bool context_set_unlink_id(Context *ctx, term link_pid, uint64_t *unlink_id)
739
819
struct ListHead * item ;
740
820
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
741
821
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
742
- if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
822
+ if (term_is_local_pid_or_port ( link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
743
823
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
744
824
if (link -> link_local_process_id == link_pid ) {
745
825
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
@@ -751,6 +831,21 @@ bool context_set_unlink_id(Context *ctx, term link_pid, uint64_t *unlink_id)
751
831
return false;
752
832
}
753
833
}
834
+ } else if (term_is_external_pid (link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
835
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
836
+ if (link -> node == term_get_external_node (link_pid )
837
+ && link -> pid_number == term_get_external_pid_process_id (link_pid )
838
+ && link -> pid_serial == term_get_external_pid_serial (link_pid )
839
+ && link -> creation == term_get_external_node_creation (link_pid )) {
840
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
841
+ uint64_t new_id = globalcontext_get_ref_ticks (ctx -> global );
842
+ link -> unlink_id = new_id ;
843
+ * unlink_id = new_id ;
844
+ return true;
845
+ } else {
846
+ return false;
847
+ }
848
+ }
754
849
}
755
850
}
756
851
return false;
@@ -761,7 +856,7 @@ void context_ack_unlink(Context *ctx, term link_pid, uint64_t unlink_id, bool pr
761
856
struct ListHead * item ;
762
857
LIST_FOR_EACH (item , & ctx -> monitors_head ) {
763
858
struct Monitor * monitor = GET_LIST_ENTRY (item , struct Monitor , monitor_list_head );
764
- if (monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
859
+ if (term_is_local_pid_or_port ( link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_LOCAL ) {
765
860
struct LinkLocalMonitor * link = CONTAINER_OF (monitor , struct LinkLocalMonitor , monitor );
766
861
if (link -> link_local_process_id == link_pid ) {
767
862
if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
@@ -785,6 +880,20 @@ void context_ack_unlink(Context *ctx, term link_pid, uint64_t unlink_id, bool pr
785
880
}
786
881
return ;
787
882
}
883
+ } else if (term_is_external_pid (link_pid ) && monitor -> monitor_type == CONTEXT_MONITOR_LINK_REMOTE ) {
884
+ struct LinkRemoteMonitor * link = CONTAINER_OF (monitor , struct LinkRemoteMonitor , monitor );
885
+ if (link -> node == term_get_external_node (link_pid )
886
+ && link -> pid_number == term_get_external_pid_process_id (link_pid )
887
+ && link -> pid_serial == term_get_external_pid_serial (link_pid )
888
+ && link -> creation == term_get_external_node_creation (link_pid )) {
889
+ if (link -> unlink_id == UNLINK_ID_LINK_ACTIVE ) {
890
+ // Send ack and remove link
891
+ dist_send_unlink_id_ack (unlink_id , term_from_local_process_id (ctx -> process_id ), link_pid , ctx );
892
+ list_remove (& monitor -> monitor_list_head );
893
+ free (monitor );
894
+ }
895
+ return ;
896
+ }
788
897
}
789
898
}
790
899
}
@@ -833,6 +942,7 @@ void context_demonitor(Context *ctx, uint64_t ref_ticks)
833
942
}
834
943
}
835
944
case CONTEXT_MONITOR_LINK_LOCAL :
945
+ case CONTEXT_MONITOR_LINK_REMOTE :
836
946
break ;
837
947
}
838
948
}
@@ -854,6 +964,7 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
854
964
break ;
855
965
}
856
966
case CONTEXT_MONITOR_LINK_LOCAL :
967
+ case CONTEXT_MONITOR_LINK_REMOTE :
857
968
case CONTEXT_MONITOR_RESOURCE :
858
969
break ;
859
970
}
0 commit comments