1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(monitor_SUITE). 22 23-include_lib("common_test/include/ct.hrl"). 24-include_lib("eunit/include/eunit.hrl"). 25 26-export([all/0, suite/0, groups/0, 27 case_1/1, case_1a/1, case_2/1, case_2a/1, mon_e_1/1, demon_e_1/1, demon_1/1, 28 demon_2/1, demon_3/1, demonitor_flush/1, 29 local_remove_monitor/1, remote_remove_monitor/1, mon_1/1, mon_2/1, 30 large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1, 31 monitor_time_offset/1]). 32 33-export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]). 34 35suite() -> 36 [{ct_hooks,[ts_install_cth]}, 37 {timetrap, {minutes, 15}}]. 38 39all() -> 40 [case_1, case_1a, case_2, case_2a, mon_e_1, demon_e_1, 41 demon_1, mon_1, mon_2, demon_2, demon_3, 42 demonitor_flush, {group, remove_monitor}, large_exit, 43 list_cleanup, mixer, named_down, otp_5827, 44 monitor_time_offset]. 45 46groups() -> 47 [{remove_monitor, [], 48 [local_remove_monitor, remote_remove_monitor]}]. 49 50%% A monitors B, B kills A and then exits (yielded core dump) 51case_1(Config) when is_list(Config) -> 52 process_flag(trap_exit, true), 53 spawn_link(?MODULE, g0, []), 54 receive _ -> ok end, 55 ok. 56 57%% A monitors B, B kills A and then exits (yielded core dump) 58case_1a(Config) when is_list(Config) -> 59 process_flag(trap_exit, true), 60 spawn_link(?MODULE, g1, []), 61 receive _ -> ok end, 62 ok. 63 64g0() -> 65 B = spawn(?MODULE, g, [self()]), 66 erlang:monitor(process, B), 67 B ! ok, 68 receive ok -> ok end, 69 ok. 70 71g1() -> 72 {B,_} = spawn_monitor(?MODULE, g, [self()]), 73 B ! ok, 74 receive ok -> ok end, 75 ok. 76 77g(Parent) -> 78 receive ok -> ok end, 79 exit(Parent, foo), 80 ok. 81 82 83%% A monitors B, B demonitors A (yielded core dump) 84case_2(Config) when is_list(Config) -> 85 B = spawn(?MODULE, y2, [self()]), 86 R = erlang:monitor(process, B), 87 B ! R, 88 receive 89 true -> ok; 90 Other -> 91 ct:fail({rec, Other}) 92 end, 93 expect_down(R, B, normal), 94 ok. 95 96%% A monitors B, B demonitors A (yielded core dump) 97case_2a(Config) when is_list(Config) -> 98 {B,R} = spawn_monitor(?MODULE, y2, [self()]), 99 B ! R, 100 receive 101 true -> ok; 102 Other -> 103 ct:fail({rec, Other}) 104 end, 105 expect_down(R, B, normal), 106 ok. 107 108y2(Parent) -> 109 R = receive T -> T end, 110 Parent ! (catch erlang:demonitor(R)), 111 ok. 112 113expect_down(Ref, P) -> 114 receive 115 {'DOWN', Ref, process, P, Reason} -> 116 Reason; 117 Other -> 118 ct:fail({rec, Other}) 119 end. 120 121expect_down(Ref, P, Reason) -> 122 receive 123 {'DOWN', Ref, process, P, Reason} -> 124 ok; 125 Other -> 126 ct:fail({rec, Other}) 127 end. 128 129expect_no_msg() -> 130 receive 131 Msg -> 132 ct:fail({msg, Msg}) 133 after 0 -> 134 ok 135 end. 136 137%%% Error cases for monitor/2 138 139mon_e_1(Config) when is_list(Config) -> 140 {ok, N} = test_server:start_node(hej, slave, []), 141 mon_error(plutt, self()), 142 mon_error(process, [bingo]), 143 mon_error(process, {rex, N, junk}), 144 mon_error(process, 1), 145 146 true = test_server:stop_node(N), 147 ok. 148 149%%% We would also like to have a test case that tries to monitor something 150%%% on an R5 node, but this isn't possible to do systematically. 151%%% 152%%% Likewise against an R6 node, which is not capable of monitoring 153%%% by name, which gives a badarg on the R7 node at the call to 154%%% erlang:monitor(process, {Name, Node}). This has been tested 155%%% manually at least once. 156 157mon_error(Type, Item) -> 158 case catch erlang:monitor(Type, Item) of 159 {'EXIT', _} -> 160 ok; 161 Other -> 162 ct:fail({err, Other}) 163 end. 164 165%%% Error cases for demonitor/1 166 167demon_e_1(Config) when is_list(Config) -> 168 {ok, N} = test_server:start_node(hej, slave, []), 169 demon_error(plutt, badarg), 170 demon_error(1, badarg), 171 172 %% Demonitor with ref created at other node 173 R1 = rpc:call(N, erlang, make_ref, []), 174 demon_error(R1, badarg), 175 176 %% Demonitor with ref created at wrong monitor link end 177 P0 = self(), 178 P2 = spawn( 179 fun() -> 180 P0 ! {self(), ref, erlang:monitor(process,P0)}, 181 receive {P0, stop} -> ok end 182 end ), 183 receive 184 {P2, ref, R2} -> 185 true = erlang:demonitor(R2), 186 P2 ! {self(), stop}; 187 Other2 -> 188 ct:fail({rec, Other2}) 189 end, 190 191 true = test_server:stop_node(N), 192 ok. 193 194demon_error(Ref, Reason) -> 195 case catch erlang:demonitor(Ref) of 196 {'EXIT', {Reason, _}} -> 197 ok; 198 Other -> 199 ct:fail({err, Other}) 200 end. 201 202%%% No-op cases for demonitor/1 203 204demon_1(Config) when is_list(Config) -> 205 true = erlang:demonitor(make_ref()), 206 ok. 207 208 209%%% Cases for demonitor/1 210 211demon_2(Config) when is_list(Config) -> 212 R1 = erlang:monitor(process, self()), 213 true = erlang:demonitor(R1), 214 %% Extra demonitor 215 true = erlang:demonitor(R1), 216 expect_no_msg(), 217 218 %% Normal 'DOWN' 219 P2 = spawn(timer, sleep, [1]), 220 R2 = erlang:monitor(process, P2), 221 case expect_down(R2, P2) of 222 normal -> ok; 223 noproc -> ok; 224 BadReason -> ct:fail({bad_reason, BadReason}) 225 end, 226 227 %% OTP-5772 228 % %% 'DOWN' before demonitor 229 % P3 = spawn(timer, sleep, [100000]), 230 % R3 = erlang:monitor(process, P3), 231 % exit(P3, frop), 232 % erlang:demonitor(R3), 233 % expect_down(R3, P3, frop), 234 235 %% Demonitor before 'DOWN' 236 P4 = spawn(timer, sleep, [100000]), 237 R4 = erlang:monitor(process, P4), 238 erlang:demonitor(R4), 239 exit(P4, frop), 240 expect_no_msg(), 241 242 ok. 243 244%% Distributed case for demonitor/1 (OTP-3499) 245demon_3(Config) when is_list(Config) -> 246 {ok, N} = test_server:start_node(hej, slave, []), 247 248 %% 'DOWN' before demonitor 249 P2 = spawn(N, timer, sleep, [100000]), 250 R2 = erlang:monitor(process, P2), 251 true = test_server:stop_node(N), 252 true = erlang:demonitor(R2), 253 expect_down(R2, P2, noconnection), 254 255 {ok, N2} = test_server:start_node(hej, slave, []), 256 257 %% Demonitor before 'DOWN' 258 P3 = spawn(N2, timer, sleep, [100000]), 259 R3 = erlang:monitor(process, P3), 260 true = erlang:demonitor(R3), 261 true = test_server:stop_node(N2), 262 expect_no_msg(), 263 264 ok. 265 266demonitor_flush(Config) when is_list(Config) -> 267 {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), flush)), 268 {'EXIT', {badarg, _}} = (catch erlang:demonitor(make_ref(), [flus])), 269 {'EXIT', {badarg, _}} = (catch erlang:demonitor(x, [flush])), 270 {ok, N} = test_server:start_node(demonitor_flush, slave, []), 271 ok = demonitor_flush_test(N), 272 true = test_server:stop_node(N), 273 ok = demonitor_flush_test(node()). 274 275demonitor_flush_test(Node) -> 276 P = spawn(Node, timer, sleep, [100000]), 277 M1 = erlang:monitor(process, P), 278 M2 = erlang:monitor(process, P), 279 M3 = erlang:monitor(process, P), 280 M4 = erlang:monitor(process, P), 281 true = erlang:demonitor(M1, [flush, flush]), 282 exit(P, bang), 283 receive {'DOWN', M2, process, P, bang} -> ok end, 284 receive after 100 -> ok end, 285 true = erlang:demonitor(M3, [flush]), 286 true = erlang:demonitor(M4, []), 287 receive {'DOWN', M4, process, P, bang} -> ok end, 288 receive 289 {'DOWN', M, _, _, _} =DM when M == M1, 290 M == M3 -> 291 ct:fail({unexpected_down_message, DM}) 292 after 100 -> 293 ok 294 end. 295 296-define(RM_MON_GROUPS, 100). 297-define(RM_MON_GPROCS, 100). 298 299 300local_remove_monitor(Config) when is_list(Config) -> 301 Gs = generate(fun () -> start_remove_monitor_group(node()) end, 302 ?RM_MON_GROUPS), 303 {True, False} = lists:foldl(fun (G, {T, F}) -> 304 receive 305 {rm_mon_res, G, {GT, GF}} -> 306 {T+GT, F+GF} 307 end 308 end, 309 {0, 0}, 310 Gs), 311 erlang:display({local_remove_monitor, True, False}), 312 {comment, 313 "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. 314 315remote_remove_monitor(Config) when is_list(Config) -> 316 {ok, N} = test_server:start_node(demonitor_flush, slave, []), 317 Gs = generate(fun () -> start_remove_monitor_group(N) end, 318 ?RM_MON_GROUPS), 319 {True, False} = lists:foldl(fun (G, {T, F}) -> 320 receive 321 {rm_mon_res, G, {GT, GF}} -> 322 {T+GT, F+GF} 323 end 324 end, 325 {0, 0}, 326 Gs), 327 erlang:display({remote_remove_monitor, True, False}), 328 true = test_server:stop_node(N), 329 {comment, 330 "True = "++integer_to_list(True)++"; False = "++integer_to_list(False)}. 331 332start_remove_monitor_group(Node) -> 333 Master = self(), 334 spawn_link( 335 fun () -> 336 Ms = generate(fun () -> 337 P = spawn(Node, fun () -> ok end), 338 erlang:monitor(process, P) 339 end, ?RM_MON_GPROCS), 340 Res = lists:foldl(fun (M, {T, F}) -> 341 case erlang:demonitor(M, [info]) of 342 true -> 343 receive 344 {'DOWN', M, _, _, _} -> 345 exit(down_msg_found) 346 after 0 -> 347 ok 348 end, 349 {T+1, F}; 350 false -> 351 receive 352 {'DOWN', M, _, _, _} -> 353 ok 354 after 0 -> 355 exit(no_down_msg_found) 356 end, 357 {T, F+1} 358 end 359 end, 360 {0,0}, 361 Ms), 362 Master ! {rm_mon_res, self(), Res} 363 end). 364 365 366%%% Cases for monitor/2 367 368mon_1(Config) when is_list(Config) -> 369 %% Normal case 370 P2 = spawn(timer, sleep, [1]), 371 R2 = erlang:monitor(process, P2), 372 case expect_down(R2, P2) of 373 normal -> ok; 374 noproc -> ok; 375 BadReason -> ct:fail({bad_reason, BadReason}) 376 end, 377 {P2A,R2A} = spawn_monitor(timer, sleep, [1]), 378 expect_down(R2A, P2A, normal), 379 380 %% 'DOWN' with other reason 381 P3 = spawn(timer, sleep, [100000]), 382 R3 = erlang:monitor(process, P3), 383 exit(P3, frop), 384 expect_down(R3, P3, frop), 385 {P3A,R3A} = spawn_monitor(timer, sleep, [100000]), 386 exit(P3A, frop), 387 expect_down(R3A, P3A, frop), 388 389 %% Monitor fails because process is dead 390 R4 = erlang:monitor(process, P3), 391 expect_down(R4, P3, noproc), 392 393 %% Normal case (named process) 394 P5 = start_jeeves(jeeves), 395 R5 = erlang:monitor(process, jeeves), 396 tell_jeeves(P5, stop), 397 expect_down(R5, {jeeves, node()}, normal), 398 399 %% 'DOWN' with other reason and node explicit activation 400 P6 = start_jeeves(jeeves), 401 R6 = erlang:monitor(process, {jeeves, node()}), 402 tell_jeeves(P6, {exit, frop}), 403 expect_down(R6, {jeeves, node()}, frop), 404 405 %% Monitor (named process) fails because process is dead 406 R7 = erlang:monitor(process, {jeeves, node()}), 407 expect_down(R7, {jeeves, node()}, noproc), 408 409 ok. 410 411%% Distributed cases for monitor/2 412mon_2(Config) when is_list(Config) -> 413 {ok, N1} = test_server:start_node(hej1, slave, []), 414 415 %% Normal case 416 P2 = spawn(N1, timer, sleep, [4000]), 417 R2 = erlang:monitor(process, P2), 418 expect_down(R2, P2, normal), 419 420 %% 'DOWN' with other reason 421 P3 = spawn(N1, timer, sleep, [100000]), 422 R3 = erlang:monitor(process, P3), 423 exit(P3, frop), 424 expect_down(R3, P3, frop), 425 426 %% Monitor fails because process is dead 427 R4 = erlang:monitor(process, P3), 428 expect_down(R4, P3, noproc), 429 430 %% Other node goes down 431 P5 = spawn(N1, timer, sleep, [100000]), 432 R5 = erlang:monitor(process, P5), 433 434 true = test_server:stop_node(N1), 435 436 expect_down(R5, P5, noconnection), 437 438 %% Monitor fails because other node is dead 439 P6 = spawn(N1, timer, sleep, [100000]), 440 R6 = erlang:monitor(process, P6), 441 R6_Reason = expect_down(R6, P6), 442 true = (R6_Reason == noconnection) orelse (R6_Reason == noproc), 443 444 %% Start a new node that can load code in this module 445 PA = filename:dirname(code:which(?MODULE)), 446 {ok, N2} = test_server:start_node 447 (hej2, slave, [{args, "-pa " ++ PA}]), 448 449 %% Normal case (named process) 450 P7 = start_jeeves({jeeves, N2}), 451 R7 = erlang:monitor(process, {jeeves, N2}), 452 tell_jeeves(P7, stop), 453 expect_down(R7, {jeeves, N2}, normal), 454 455 %% 'DOWN' with other reason (named process) 456 P8 = start_jeeves({jeeves, N2}), 457 R8 = erlang:monitor(process, {jeeves, N2}), 458 tell_jeeves(P8, {exit, frop}), 459 expect_down(R8, {jeeves, N2}, frop), 460 461 %% Monitor (named process) fails because process is dead 462 R9 = erlang:monitor(process, {jeeves, N2}), 463 expect_down(R9, {jeeves, N2}, noproc), 464 465 %% Other node goes down (named process) 466 _P10 = start_jeeves({jeeves, N2}), 467 R10 = erlang:monitor(process, {jeeves, N2}), 468 469 true = test_server:stop_node(N2), 470 471 expect_down(R10, {jeeves, N2}, noconnection), 472 473 %% Monitor (named process) fails because other node is dead 474 R11 = erlang:monitor(process, {jeeves, N2}), 475 expect_down(R11, {jeeves, N2}, noconnection), 476 477 ok. 478 479%%% Large exit reason. Crashed first attempt to release R5B. 480 481large_exit(Config) when is_list(Config) -> 482 f(100), 483 ok. 484 485f(0) -> 486 ok; 487f(N) -> 488 f(), 489 f(N-1). 490 491f() -> 492 S0 = {big, tuple, with, [list, 4563784278]}, 493 S = {S0, term_to_binary(S0)}, 494 P = spawn(?MODULE, large_exit_sub, [S]), 495 R = erlang:monitor(process, P), 496 P ! hej, 497 receive 498 {'DOWN', R, process, P, X} -> 499 io:format(" -> ~p~n", [X]), 500 if 501 X == S -> 502 ok; 503 true -> 504 ct:fail({X, S}) 505 end; 506 Other -> 507 io:format(" -> ~p~n", [Other]), 508 exit({answer, Other}) 509 end. 510 511large_exit_sub(S) -> 512 receive _X -> ok end, 513 exit(S). 514 515%%% Testing of monitor link list cleanup 516%%% by using erlang:process_info(self(), monitors) 517%%% and erlang:process_info(self(), monitored_by) 518 519list_cleanup(Config) when is_list(Config) -> 520 P0 = self(), 521 M = node(), 522 PA = filename:dirname(code:which(?MODULE)), 523 true = register(master_bertie, self()), 524 525 %% Normal local case, monitor and demonitor 526 P1 = start_jeeves(jeeves), 527 {[], []} = monitors(), 528 expect_jeeves(P1, monitors, {monitors, {[], []}}), 529 R1a = erlang:monitor(process, P1), 530 {[{process, P1}], []} = monitors(), 531 expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), 532 true = erlang:demonitor(R1a), 533 expect_no_msg(), 534 {[], []} = monitors(), 535 expect_jeeves(P1, monitors, {monitors, {[], []}}), 536 %% Remonitor named and try again, now exiting the monitored process 537 R1b = erlang:monitor(process, jeeves), 538 {[{process, {jeeves, M}}], []} = monitors(), 539 expect_jeeves(P1, monitors, {monitors, {[], [P0]}}), 540 tell_jeeves(P1, stop), 541 expect_down(R1b, {jeeves, node()}, normal), 542 {[], []} = monitors(), 543 544 %% Slightly weird local case - the monitoring process crashes 545 P2 = start_jeeves(jeeves), 546 {[], []} = monitors(), 547 expect_jeeves(P2, monitors, {monitors, {[], []}}), 548 {monitor_process, _R2} = 549 ask_jeeves(P2, {monitor_process, master_bertie}), 550 {[], [P2]} = monitors(), 551 expect_jeeves(P2, monitors, 552 {monitors, {[{process, {master_bertie, node()}}], []}}), 553 tell_jeeves(P2, {exit, frop}), 554 timer:sleep(2000), 555 {[], []} = monitors(), 556 557 %% Start a new node that can load code in this module 558 {ok, J} = test_server:start_node 559 (jeeves, slave, [{args, "-pa " ++ PA}]), 560 561 %% Normal remote case, monitor and demonitor 562 P3 = start_jeeves({jeeves, J}), 563 {[], []} = monitors(), 564 expect_jeeves(P3, monitors, {monitors, {[], []}}), 565 R3a = erlang:monitor(process, P3), 566 {[{process, P3}], []} = monitors(), 567 expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), 568 true = erlang:demonitor(R3a), 569 expect_no_msg(), 570 {[], []} = monitors(), 571 expect_jeeves(P3, monitors, {monitors, {[], []}}), 572 %% Remonitor named and try again, now exiting the monitored process 573 R3b = erlang:monitor(process, {jeeves, J}), 574 {[{process, {jeeves, J}}], []} = monitors(), 575 expect_jeeves(P3, monitors, {monitors, {[], [P0]}}), 576 tell_jeeves(P3, stop), 577 expect_down(R3b, {jeeves, J}, normal), 578 {[], []} = monitors(), 579 580 %% Slightly weird remote case - the monitoring process crashes 581 P4 = start_jeeves({jeeves, J}), 582 {[], []} = monitors(), 583 expect_jeeves(P4, monitors, {monitors, {[], []}}), 584 {monitor_process, _R4} = 585 ask_jeeves(P4, {monitor_process, {master_bertie, M}}), 586 {[], [P4]} = monitors(), 587 expect_jeeves(P4, monitors, 588 {monitors, {[{process, {master_bertie, M}}], []}} ), 589 tell_jeeves(P4, {exit, frop}), 590 timer:sleep(2000), 591 {[], []} = monitors(), 592 593 %% Now, the monitoring remote node crashes 594 P5 = start_jeeves({jeeves, J}), 595 {[], []} = monitors(), 596 expect_jeeves(P5, monitors, {monitors, {[], []}}), 597 {monitor_process, _R5} = 598 ask_jeeves(P5, {monitor_process, P0}), 599 {[], [P5]} = monitors(), 600 expect_jeeves(P5, monitors, 601 {monitors, {[{process, P0}], []}} ), 602 test_server:stop_node(J), 603 timer:sleep(4000), 604 {[], []} = monitors(), 605 606 true = unregister(master_bertie), 607 ok. 608 609 610%%% Mixed internal and external monitors 611 612mixer(Config) when is_list(Config) -> 613 PA = filename:dirname(code:which(?MODULE)), 614 NN = [j0,j1,j2], 615 NL0 = [begin 616 {ok, J} = test_server:start_node(X,slave,[{args, "-pa " ++ PA}]), 617 J 618 end || X <- NN], 619 NL1 = lists:duplicate(2,node()) ++ NL0, 620 Perm = perm(NL1), 621 lists:foreach( 622 fun(NL) -> 623 Js = [start_jeeves({[],M}) || M <- (NL ++ NL)], 624 [ask_jeeves(P,{monitor_process,self()}) || P <- Js], 625 {monitored_by,MB} = process_info(self(),monitored_by), 626 MBL = lists:sort(MB), 627 JsL = lists:sort(Js), 628 MBL = JsL, 629 {monitors,[]} = process_info(self(),monitors), 630 [tell_jeeves(P,{exit,flaff}) || P <- Js], 631 wait_for_m([],[],200) 632 end, 633 Perm), 634 lists:foreach( 635 fun(NL) -> 636 Js = [start_jeeves({[],M}) || M <- (NL ++ NL)], 637 Rs = [begin 638 {monitor_process,Ref} = ask_jeeves(P,{monitor_process,self()}), 639 {P,Ref} 640 end || P <- Js], 641 {monitored_by,MB} = process_info(self(),monitored_by), 642 MBL = lists:sort(MB), 643 JsL = lists:sort(Js), 644 MBL = JsL, 645 {monitors,[]} = process_info(self(),monitors), 646 [ask_jeeves(P,{demonitor,Ref}) || {P,Ref} <- Rs], 647 wait_for_m([],[],200), 648 [tell_jeeves(P,{exit,flaff}) || P <- Js] 649 end, 650 Perm), 651 lists:foreach( 652 fun(NL) -> 653 Js = [start_jeeves({[],M}) || M <- (NL ++ NL)], 654 [ask_jeeves(P,{monitor_process,self()}) || P <- Js], 655 [erlang:monitor(process,P) || P <- Js], 656 {monitored_by,MB} = process_info(self(),monitored_by), 657 MBL = lists:sort(MB), 658 JsL = lists:sort(Js), 659 MBL = JsL, 660 {monitors,M} = process_info(self(),monitors), 661 ML = lists:sort([P||{process,P} <- M]), 662 ML = JsL, 663 [begin 664 tell_jeeves(P,{exit,flaff}), 665 receive {'DOWN',_,process,P,_} -> ok end 666 end || P <- Js], 667 wait_for_m([],[],200) 668 end, 669 Perm), 670 lists:foreach( 671 fun(NL) -> 672 Js = [start_jeeves({[],M}) || M <- (NL ++ NL)], 673 Rs = [begin 674 {monitor_process,Ref} = ask_jeeves(P,{monitor_process,self()}), 675 {P,Ref} 676 end || P <- Js], 677 R2s = [{P,erlang:monitor(process,P)} || P <- Js], 678 {monitored_by,MB} = process_info(self(),monitored_by), 679 MBL = lists:sort(MB), 680 JsL = lists:sort(Js), 681 MBL = JsL, 682 {monitors,M} = process_info(self(),monitors), 683 ML = lists:sort([P||{process,P} <- M]), 684 ML = JsL, 685 [ask_jeeves(P,{demonitor,Ref}) || {P,Ref} <- Rs], 686 wait_for_m(lists:sort(M),[],200), 687 [erlang:demonitor(Ref) || {_P,Ref} <- R2s], 688 wait_for_m([],[],200), 689 [tell_jeeves(P,{exit,flaff}) || P <- Js] 690 end, 691 Perm), 692 [test_server:stop_node(K) || K <- NL0], 693 ok. 694 695%% Test that DOWN message for a named monitor isn't 696%% delivered until name has been unregistered 697named_down(Config) when is_list(Config) -> 698 Name = list_to_atom(atom_to_list(?MODULE) 699 ++ "-named_down-" 700 ++ integer_to_list(erlang:system_time(second)) 701 ++ "-" ++ integer_to_list(erlang:unique_integer([positive]))), 702 Prio = process_flag(priority,high), 703 %% Spawn a bunch of high prio cpu bound processes to prevent 704 %% normal prio processes from terminating during the next 705 %% 500 ms... 706 Self = self(), 707 spawn_opt(fun () -> 708 WFun = fun 709 (F, hej) -> F(F, hopp); 710 (F, hopp) -> F(F, hej) 711 end, 712 NoSchedulers = erlang:system_info(schedulers_online), 713 lists:foreach(fun (_) -> 714 spawn_opt(fun () -> 715 WFun(WFun, 716 hej) 717 end, 718 [{priority,high}, 719 link]) 720 end, 721 lists:seq(1, NoSchedulers)), 722 receive after 500 -> ok end, 723 unlink(Self), 724 exit(bang) 725 end, 726 [{priority,high}, link]), 727 NamedProc = spawn_link(fun () -> 728 receive after infinity -> ok end 729 end), 730 ?assertEqual(true, register(Name, NamedProc)), 731 unlink(NamedProc), 732 Mon = erlang:monitor(process, Name), 733 exit(NamedProc, bang), 734 receive {'DOWN',Mon, _, _, bang} -> ok 735 after 3000 -> ?assert(false) end, 736 ?assertEqual(true, register(Name, self())), 737 ?assertEqual(true, unregister(Name)), 738 process_flag(priority,Prio), 739 ok. 740 741otp_5827(Config) when is_list(Config) -> 742 %% Make a pid with the same nodename but with another creation 743 [CreEnd | RPTail] 744 = lists:reverse(binary_to_list(term_to_binary(self()))), 745 NewCreEnd = case CreEnd of 746 0 -> 1; 747 1 -> 2; 748 _ -> CreEnd - 1 749 end, 750 OtherCreationPid 751 = binary_to_term(list_to_binary(lists:reverse([NewCreEnd | RPTail]))), 752 %% If the bug is present erlang:monitor(process, OtherCreationPid) 753 %% will hang... 754 Parent = self(), 755 Ok = make_ref(), 756 spawn(fun () -> 757 Mon = erlang:monitor(process, OtherCreationPid), 758 % Should get the DOWN message right away 759 receive 760 {'DOWN', Mon, process, OtherCreationPid, noproc} -> 761 Parent ! Ok 762 end 763 end), 764 receive 765 Ok -> 766 ok 767 after 1000 -> 768 ct:fail("erlang:monitor/2 hangs") 769 end. 770 771monitor_time_offset(Config) when is_list(Config) -> 772 {ok, Node} = start_node(Config, "+C single_time_warp"), 773 Me = self(), 774 PMs = lists:map(fun (_) -> 775 Pid = spawn(Node, 776 fun () -> 777 check_monitor_time_offset(Me) 778 end), 779 {Pid, erlang:monitor(process, Pid)} 780 end, 781 lists:seq(1, 100)), 782 lists:foreach(fun ({P, _M}) -> 783 P ! check_no_change_message 784 end, PMs), 785 lists:foreach(fun ({P, M}) -> 786 receive 787 {no_change_message_received, P} -> 788 ok; 789 {'DOWN', M, process, P, Reason} -> 790 ct:fail(Reason) 791 end 792 end, PMs), 793 preliminary = rpc:call(Node, erlang, system_flag, [time_offset, finalize]), 794 lists:foreach(fun ({P, M}) -> 795 receive 796 {change_messages_received, P} -> 797 erlang:demonitor(M, [flush]); 798 {'DOWN', M, process, P, Reason} -> 799 ct:fail(Reason) 800 end 801 end, PMs), 802 stop_node(Node), 803 ok. 804 805check_monitor_time_offset(Leader) -> 806 Mon1 = erlang:monitor(time_offset, clock_service), 807 Mon2 = erlang:monitor(time_offset, clock_service), 808 Mon3 = erlang:monitor(time_offset, clock_service), 809 Mon4 = erlang:monitor(time_offset, clock_service), 810 811 erlang:demonitor(Mon2, [flush]), 812 813 Mon5 = erlang:monitor(time_offset, clock_service), 814 Mon6 = erlang:monitor(time_offset, clock_service), 815 Mon7 = erlang:monitor(time_offset, clock_service), 816 817 receive check_no_change_message -> ok end, 818 receive 819 {'CHANGE', _, time_offset, clock_service, _} -> 820 exit(unexpected_change_message_received) 821 after 0 -> 822 Leader ! {no_change_message_received, self()} 823 end, 824 receive after 100 -> ok end, 825 erlang:demonitor(Mon4, [flush]), 826 receive 827 {'CHANGE', Mon3, time_offset, clock_service, _} -> 828 ok 829 end, 830 receive 831 {'CHANGE', Mon6, time_offset, clock_service, _} -> 832 ok 833 end, 834 erlang:demonitor(Mon5, [flush]), 835 receive 836 {'CHANGE', Mon7, time_offset, clock_service, _} -> 837 ok 838 end, 839 receive 840 {'CHANGE', Mon1, time_offset, clock_service, _} -> 841 ok 842 end, 843 receive 844 {'CHANGE', _, time_offset, clock_service, _} -> 845 exit(unexpected_change_message_received) 846 after 1000 -> 847 ok 848 end, 849 Leader ! {change_messages_received, self()}. 850 851%% 852%% ... 853%% 854 855wait_for_m(_,_,0) -> 856 exit(monitor_wait_timeout); 857wait_for_m(Monitors, MonitoredBy, N) -> 858 {monitors,M0} = process_info(self(),monitors), 859 {monitored_by,MB0} = process_info(self(),monitored_by), 860 case lists:sort(M0) of 861 Monitors -> 862 case lists:sort(MB0) of 863 MonitoredBy -> 864 ok; 865 _ -> 866 receive after 100 -> ok end, 867 wait_for_m(Monitors,MonitoredBy,N-1) 868 end; 869 _ -> 870 receive after 100 -> ok end, 871 wait_for_m(Monitors,MonitoredBy,N-1) 872 end. 873 874% All permutations of a list... 875perm([]) -> 876 []; 877perm([X]) -> 878 [[X]]; 879perm(List) -> 880 perm([],List,[]). 881 882perm(_,[],Acc) -> 883 Acc; 884perm(Pre,[El|Post],Acc) -> 885 Res = [[El|X] || X <- perm(Pre ++ Post)], 886 perm(Pre ++ [El], Post, Res ++ Acc). 887 888 889%%% Our butler for named process monitor tests 890 891jeeves(Parent, Name, Ref) 892 when is_pid(Parent), (is_atom(Name) or (Name =:= [])), is_reference(Ref) -> 893 %%io:format("monitor_SUITE:jeeves(~p, ~p)~n", [Parent, Name]), 894 case Name of 895 Atom when is_atom(Atom) -> 896 register(Name, self()); 897 [] -> 898 ok 899 end, 900 Parent ! {self(), Ref}, 901 jeeves_loop(Parent). 902 903jeeves_loop(Parent) -> 904 receive 905 {Parent, monitors} -> 906 Parent ! {self(), {monitors, monitors()}}, 907 jeeves_loop(Parent); 908 {Parent, {monitor_process, P}} -> 909 Parent ! {self(), {monitor_process, 910 catch erlang:monitor(process, P) }}, 911 jeeves_loop(Parent); 912 {Parent, {demonitor, Ref}} -> 913 Parent ! {self(), {demonitor, catch erlang:demonitor(Ref)}}, 914 jeeves_loop(Parent); 915 {Parent, stop} -> 916 ok; 917 {Parent, {exit, Reason}} -> 918 exit(Reason); 919 Other -> 920 io:format("~p:jeeves_loop received ~p~n", [?MODULE, Other]) 921 end. 922 923 924start_jeeves({Name, Node}) 925 when (is_atom(Name) or (Name =:= [])), is_atom(Node) -> 926 Parent = self(), 927 Ref = make_ref(), 928 Pid = spawn(Node, fun() -> jeeves(Parent, Name, Ref) end), 929 receive 930 {Pid, Ref} -> 931 ok; 932 Other -> 933 ct:fail({rec, Other}) 934 end, 935 Pid; 936start_jeeves(Name) when is_atom(Name) -> 937 start_jeeves({Name, node()}). 938 939 940tell_jeeves(Pid, What) when is_pid(Pid) -> 941 Pid ! {self(), What}. 942 943 944ask_jeeves(Pid, Request) when is_pid(Pid) -> 945 Pid ! {self(), Request}, 946 receive 947 {Pid, Response} -> 948 Response; 949 Other -> 950 ct:fail({rec, Other}) 951 end. 952 953 954expect_jeeves(Pid, Request, Response) when is_pid(Pid) -> 955 Pid ! {self(), Request}, 956 receive 957 {Pid, Response} -> 958 ok; 959 Other -> 960 ct:fail({rec, Other}) 961 end. 962 963 964monitors() -> 965 monitors(self()). 966 967monitors(Pid) when is_pid(Pid) -> 968 {monitors, Monitors} = process_info(self(), monitors), 969 {monitored_by, MonitoredBy} = process_info(self(), monitored_by), 970 {Monitors, MonitoredBy}. 971 972generate(_Fun, 0) -> 973 []; 974generate(Fun, N) -> 975 [Fun() | generate(Fun, N-1)]. 976 977start_node(Config, Args) -> 978 TestCase = proplists:get_value(testcase, Config), 979 PA = filename:dirname(code:which(?MODULE)), 980 ESTime = erlang:monotonic_time(1) + erlang:time_offset(1), 981 Unique = erlang:unique_integer([positive]), 982 Name = list_to_atom(atom_to_list(?MODULE) 983 ++ "-" 984 ++ atom_to_list(TestCase) 985 ++ "-" 986 ++ integer_to_list(ESTime) 987 ++ "-" 988 ++ integer_to_list(Unique)), 989 test_server:start_node(Name, 990 slave, 991 [{args, "-pa " ++ PA ++ " " ++ Args}]). 992 993stop_node(Node) -> 994 test_server:stop_node(Node). 995