Opened 4 weeks ago
Closed 10 days ago
#393 closed defect (fixed)
absentee_listener_ has a temp_segment leak
| Reported by: | Gary Dixon | Owned by: | Eric Swenson |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | Standard Library | Version: | MR12.5 |
| Keywords: | Cc: |
Description (last modified by )
While developing an exec_com to test dump_segment and ring_zero_dump,
I checked on status of temporary segments in my process directory.
My current stack shows only an interrupted emacs editing session.
ts -bf quit condition: 234|13340 pl1_signal_$pl1_signal_from_ops_|776 (bound_library_1_|13712) 234|12320 lisp_fault_handler_$ioc|1265 (bound_lisp_intrprtr_|17521) 234|12240 lisp_subr_tv_$..lisp..|2652 (bound_lisp_intrprtr_|2652) 234|11760 lisp|1076 (bound_lisp_intrprtr_|35014) 234|11460 lisp$lisp|244 (bound_lisp_intrprtr_|34162) 234|11360 forward_command_|70 (bound_multics_emacs_|136514) 234|10260 emacs$emacs|2401 (bound_multics_emacs_|141121) 234|10140 emacs_tv_$emacs|37 (bound_emacs_full_|37) 234|5340 command_processor_$read_list|10312 (bound_multics_bce_|10312) 234|4360 command_processor_$complex_command_processor|2543 (bound_multics_bce_|2543) 234|3420 command_processor_$command_processor_|1227 (bound_multics_bce_|1227) 234|2700 abbrev$abbrev_processor|6105 (bound_command_loop_|14103) 234|2400 listen_$listen_|554 (bound_command_loop_|34522) 234|2000 initialize_process_$initialize_process_|704 (bound_process_init_|704)
However, past usage in my process shows 57 temp segments in existence, and only 6 are free. The majority of them were claimed by ec_input_ operations.
list_temp_segments
57 Segments, 6 Free
!BBBKbcHFWxfwjm.temp.0305 command_processor_
!BBBKbcHFXHQmDB.temp.0362 emacs
!BBBKbcHFXHWDLw.temp.0363 emacs
!BBBKbcHFXQKWkm.temp.0433 emacs
!BBBKbcHFXQKdqf.temp.0434 emacs
!BBBKbcHFXQQQJQ.temp.0440 emacs
!BBBKbcHFcglBfc.temp.0446 command_processor_
!BBBKbcHFcgzxdl.temp.0454 command_processor_
!BBBKbcHFchBGJp.temp.0455 command_processor_
!BBBKbcHFlpHmpB.temp.0457 ec_input_ (area)
!BBBKbcHKLmmBGD.temp.0477 ec_input_ (area)
!BBBKbcHKPddDbh.temp.0500 ec_input_ (area)
!BBBKbcHKXgkmXL.temp.0501 ec_input_ (area)
!BBBKbcHKhNnXgh.temp.0502 ec_input_ (area)
!BBBKbcHKjQFcQd.temp.0503 ec_input_ (area)
!BBBKbcHKmpMGcn.temp.0504 ec_input_ (area)
!BBBKbcHKwWbkBW.temp.0505 ec_input_ (area)
!BBBKbcHLHNqJkP.temp.0506 ec_input_ (area)
!BBBKbcHLHPLQnn.temp.0507 ec_input_ (area)
!BBBKbcHLHPLckF.temp.0510 ec_input_ (area)
!BBBKbcHLKqFlCh.temp.0511 ec_input_ (area)
!BBBKbcHLPCJbqp.temp.0512 ec_input_ (area)
!BBBKbcHLgXlKfK.temp.0565 ec_input_ (area)
!BBBKbcHLqdwQNd.temp.0566 ec_input_ (area)
!BBBKbcHLqfNBMP.temp.0570 ec_input_ (area)
!BBBKbcHMLDggcb.temp.0571 ec_input_ (area)
!BBBKbcHMcGgMgg.temp.0572 ec_input_ (area)
!BBBKbcHNQMKqkQ.temp.0573 ec_input_ (area)
!BBBKbcHNZhbKXd.temp.0574 ec_input_ (area)
!BBBKbcHNZhgHjJ.temp.0575 ec_input_ (area)
!BBBKbcHNbzlfqj.temp.0576 ec_input_ (area)
!BBBKbcHNbzqQFd.temp.0577 ec_input_ (area)
!BBBKbcHNhfZpxl.temp.0600 ec_input_ (area)
!BBBKbcHNhffjCx.temp.0601 ec_input_ (area)
!BBBKbcHNlznBFG.temp.0602 ec_input_ (area)
!BBBKbcHNlzwpKn.temp.0603 ec_input_ (area)
!BBBKbcHNpCHmNb.temp.0604 ec_input_ (area)
!BBBKbcHNpCPGCl.temp.0605 ec_input_ (area)
!BBBKbcHPGWJCbh.temp.0606 ec_input_ (area)
!BBBKbcHPGWNCQW.temp.0607 ec_input_ (area)
!BBBKbcHPJJFzxB.temp.0610 ec_input_ (area)
!BBBKbcHPJJKzpG.temp.0611 ec_input_ (area)
!BBBKbcHPMbmlQf.temp.0612 ec_input_ (area)
!BBBKbcHPMbwqnn.temp.0613 ec_input_ (area)
!BBBKbcHPPNqQCD.temp.0614 ec_input_ (area)
!BBBKbcHPPPBWHh.temp.0615 ec_input_ (area)
!BBBKbcHPccZcpJ.temp.0616 ec_input_ (area)
!BBBKbcHPccflDz.temp.0617 ring_zero_dump.1 (ring_zero_dump
!BBBKbcHQBdpnJK.temp.0624 ring_zero_dump.1 (ring_zero_dump
!BBBKbcHQgKCwQD.temp.0626 emacs
!BBBKbcHWnjHwKP.temp.0625 ring_zero_dump.1 (ring_zero_dump
ls [pd]>*.temp.* -records -dtem
Segments = 59, Records = 70.
06/21/26 10:47 1 !BBBKbcHFWxfwjm.temp.0305
06/21/26 10:47 1 !BBBKbcHFWzDFBB.temp.mail_system
06/21/26 10:47 3 !BBBKbcHFWzDZJW.temp.mail_system
06/21/26 10:47 1 !BBBKbcHFXHQmDB.temp.0362
06/21/26 10:47 1 !BBBKbcHFXHWDLw.temp.0363
06/21/26 10:47 1 !BBBKbcHFXQKWkm.temp.0433
06/21/26 10:47 1 !BBBKbcHFXQKdqf.temp.0434
06/21/26 10:47 2 !BBBKbcHFXQQQJQ.temp.0440
06/21/26 10:49 1 !BBBKbcHFcglBfc.temp.0446
06/21/26 10:49 1 !BBBKbcHFcgzxdl.temp.0454
06/21/26 10:49 1 !BBBKbcHFchBGJp.temp.0455
06/21/26 11:56 1 !BBBKbcHFlpHmpB.temp.0457
06/21/26 11:57 1 !BBBKbcHKLmmBGD.temp.0477
06/21/26 11:59 1 !BBBKbcHKPddDbh.temp.0500
06/21/26 12:03 1 !BBBKbcHKXgkmXL.temp.0501
06/21/26 12:03 1 !BBBKbcHKhNnXgh.temp.0502
06/21/26 12:05 1 !BBBKbcHKjQFcQd.temp.0503
06/21/26 12:07 1 !BBBKbcHKmpMGcn.temp.0504
06/21/26 12:12 1 !BBBKbcHKwWbkBW.temp.0505
06/21/26 12:13 1 !BBBKbcHLHNqJkP.temp.0506
06/21/26 12:15 1 !BBBKbcHLHPLQnn.temp.0507
06/21/26 12:20 1 !BBBKbcHLHPLckF.temp.0510
06/21/26 12:21 1 !BBBKbcHLKqFlCh.temp.0511
06/21/26 12:23 1 !BBBKbcHLPCJbqp.temp.0512
06/21/26 12:25 1 !BBBKbcHLgXlKfK.temp.0565
06/21/26 12:31 1 !BBBKbcHLqdwQNd.temp.0566
06/21/26 12:32 1 !BBBKbcHLqfNBMP.temp.0570
06/21/26 12:36 1 !BBBKbcHMLDggcb.temp.0571
06/21/26 12:52 1 !BBBKbcHMcGgMgg.temp.0572
06/21/26 12:53 1 !BBBKbcHNQMKqkQ.temp.0573
06/21/26 12:53 1 !BBBKbcHNZhbKXd.temp.0574
06/21/26 12:54 1 !BBBKbcHNZhgHjJ.temp.0575
06/21/26 12:54 1 !BBBKbcHNbzlfqj.temp.0576
06/21/26 12:57 1 !BBBKbcHNbzqQFd.temp.0577
06/21/26 12:57 1 !BBBKbcHNhfZpxl.temp.0600
06/21/26 12:59 1 !BBBKbcHNhffjCx.temp.0601
06/21/26 12:59 1 !BBBKbcHNlznBFG.temp.0602
06/21/26 13:00 1 !BBBKbcHNlzwpKn.temp.0603
06/21/26 13:00 1 !BBBKbcHNpCHmNb.temp.0604
06/21/26 13:05 1 !BBBKbcHNpCPGCl.temp.0605
06/21/26 13:05 1 !BBBKbcHPGWJCbh.temp.0606
06/21/26 13:06 1 !BBBKbcHPGWNCQW.temp.0607
06/21/26 13:06 1 !BBBKbcHPJJFzxB.temp.0610
06/21/26 13:08 1 !BBBKbcHPJJKzpG.temp.0611
06/21/26 13:08 1 !BBBKbcHPMbmlQf.temp.0612
06/21/26 13:09 1 !BBBKbcHPMbwqnn.temp.0613
06/21/26 13:09 1 !BBBKbcHPPNqQCD.temp.0614
06/21/26 13:12 1 !BBBKbcHPPPBWHh.temp.0615
06/21/26 13:12 1 !BBBKbcHPccZcpJ.temp.0616
06/21/26 13:12 2 !BBBKbcHPccflDz.temp.0617
06/21/26 13:21 2 !BBBKbcHQBdpnJK.temp.0624
06/21/26 13:32 13 !BBBKbcHQgKCwQD.temp.0626
06/21/26 13:53 1 !BBBKbcHWnjHwKP.temp.0625
06/21/26 13:54 0 !BBBKbcHWqwCdKj.temp.0627
06/21/26 14:14 0 !BBBKbcHZBblQlQ.temp.0632
06/21/26 14:14 0 !BBBKbcHZBblhmp.temp.0634
06/21/26 14:14 0 !BBBKbcHZBblpnZ.temp.0635
06/21/26 14:14 0 !BBBKbcHZBbwMxW.temp.0637
06/21/26 14:25 0 !BBBKbcHZdwmzKC.temp.0647
I suspect that:
- one gets created each time the exec_com command is called; and
- that temp seg isn't getting released correctly.
I have only the above proof of this suspicion at the moment, but I feel this temp segment releasing error should be documented. While temp segment sizes in the process directory are small (usually 1 page long), the leak could cause the process to eventually run out of available segment numbers. The highest user process segment number allowed is segno 1777_o = 1023_d (limited by the size of user process dseg: 2 pages with each SDW in the array occupying 2 words).
Change History (5)
comment:1 by , 4 weeks ago
| Description: | modified (diff) |
|---|
comment:2 by , 4 weeks ago
comment:3 by , 4 weeks ago
| Summary: | absentee_listener_ appears to have a temp_segment leak → absentee_listener_ has a temp_segment leak |
|---|
comment:4 by , 4 weeks ago
I believe the cause of the temp segment leak stems from the method used by absentee_listen_$execute_handler to create an almost new abs_data structure without preserving contents of the abs_data.work_area in the original abs_data structure.
The abs_data structure ends with an 800 word area called abs_data.work_area. Aspects of this structure important to this issue are shown by an excerpt from abs_io_data.incl.pl1.
declare 1 abs_data aligned based (abs_data_ptr),
2 version fixed bin, /* Version = 1 */
2 io_module_name char (32) varying, /* either "abs_io_" or "ec_input_" */
...
2 work_area area (800); /* extensible area for args, etc. */
declare abs_data_version_1 fixed bin static options (constant) initial (1),
Work_area_size fixed bin static options (constant) initial (800);
An abs_data structure is allocated whenever an exec_com script (or absentee job) begins execution. That same structure is used for allocations while the script runs, unless an on-unit established by the script gets invoked by a signal in its CONDITION_LIST.
&on CONDITION_LIST &begin LINES &end
To execute the LINES inside the on-unit, the absentee_listen_$execute_handler is called to establish a run-time environment in which to execute the on-unit lines. This is the equivalent of pushing a new stack frame onto the user stack in which to run a PL/I on-unit. The on-unit has access to the variables and labels setup by the outer script. So when the execute_handler entry allocates a new abs_data structure, it copies all of the data from the outer-script's abs_data into the new abs_data structure to capture this outer information. It then initializes some elements of the new structure for the on-unit's environment, while preserving data for the outer-script.
execute_handler: entry (P_exec_com_info_ptr, P_ec_info_ptr, P_abs_data_ptr, P_handler_node_ptr,
P_condition_info_ptr, P_goto_label_ptr, P_goto_label_len, P_continue_to_signal_sw, P_code);
/* This entry point executes the text of an &on unit as if it were a separate exec_com, remembering whether it
has exited by means of a nonlocal &goto */
entry_point_name = "execute_handler";
P_goto_label_ptr = null;
state = IN_OUTER_PROC;
initialized = "0"b;
exec_com_info_ptr = P_exec_com_info_ptr;
ec_info = P_ec_info_ptr -> ec_data;
handler_node_ptr = P_handler_node_ptr;
/* Set up a new abs_data for executing the handler */
abs_data_ptr = null;
on cleanup call clean_up;
call abs_io_$allocate_abs_data (abs_data_ptr);
abs_data = P_abs_data_ptr -> abs_data; /* will use some old information */
abs_data.active = "0"b;
call abs_io_$initialize_abs_data (abs_data_ptr); /* and some new information */
initialized = "1"b;
...
The abs_data.work_area created as an empty area which that abs_data structure is allocated is then overwritten by the outer-script's work_area. Notice the comment attached to that statement:
/* use the same area; copy it back when done */
That comment is an important clue to the losing data about components of the extensible area.
abs_data.work_area = P_abs_data_ptr -> abs_data.work_area;
/* use the same area; copy it back when done */
saved_abs_data_ptr, abs_data.on_info.parent_abs_data_ptr = ec_info.switch_ptr -> iocb.attach_data_ptr;
ec_info.switch_ptr -> iocb.attach_data_ptr = abs_data_ptr;
ec_info.call_ready_proc = "0"b;
go to COMMON;
The abs_data.work_area is an extensible area and has an extend_block allocated in the work_area (and pointed to by the area_header) to locate additional components of the area. From area_structures.incl.pl1, that extend_block is shown below.
dcl 1 extend_block aligned based (extend_blockp), /* contents of extend block for extensible areas */
2 first_area ptr unal, /* pointer to first area */
2 next_area ptr unal, /* pointer to next area in chain */
2 sequence_no fixed bin, /* sequence number for this component */
2 name char (32), /* owner of the area */
2 pad fixed; /* brings it to an even, 12 word allocation */
When the 800 words of the abs_data.work_area are filled with allocations, then the allocator calls define_area_ to add an extension area component in a temporary segment. That new area component also includes an extend_block. But the extend_block in the first area component gets updated to with information about this latest extension component being created.
Because nothing has been allocated in the new abs_data.work_area before it is overwritten by the abs_data.work_area for the outer-script, no loss of information has occurred as yet.
However, now LINES from the &on-unit being executed are read and invoked. These do cause allocations in the 800 word abs_data.work_area, which sometimes require adding a new component area to the extensible area. Such addition is recorded in the extend_block of the 800 word abs_data.work_area, and linked to any prior components in the extensible area. As yet, no data has been lost.
When execution of the &on-unit LINES finishes, absentee_listen_ jumps to the EGRESS label, which invokes the finish_up subroutine. This routine has the job of freeing the new abs_data structure, and restoring use of the prior abs_data structure. According to the comment highlighted above, contents of the 800 word first component of the abs_data.work_area is supposed to be copied back into the outer-script's work_area. But finish_up frees the new abs_data structure WITHOUT copying it back.
EGRESS:
call finish_up ();
return;
...
finish_up: procedure ();
...
if initialized then
if abs_data_ptr ^= null then
if entry_point_name = "execute_handler" then do;
P_continue_to_signal_sw = abs_data.on_info.continue_to_signal_sw;
if abs_data.goto_sw then do; /* leaving &on unit via &goto */
/* label must be allocated in parent's area */
allocate goto_label in (saved_abs_data_ptr -> abs_data.work_area)
set (P_goto_label_ptr); /* set args of absentee_listen_$execute_handler */
P_goto_label_ptr -> goto_label = abs_data.goto_label_ptr -> goto_label;
P_goto_label_len = abs_data.goto_label_len;
saved_abs_data_ptr -> abs_data.goto_statement_pos = abs_data.goto_statement_pos
+ charno (abs_data.input_string.ptr)
- charno (saved_abs_data_ptr -> abs_data.input_string.ptr);
saved_abs_data_ptr -> abs_data.goto_statement_len = abs_data.goto_statement_len;
end;
saved_abs_data_ptr -> abs_data.output_file = abs_data.output_file;
saved_abs_data_ptr -> abs_data.variables_ptr = abs_data.variables_ptr;
free abs_data; /* free the &on unit's private abs_data */
/* and restore the parent's: */
abs_data_ptr, ec_info.switch_ptr -> attach_data_ptr = saved_abs_data_ptr;
end;
return;
end finish_up;
Thus any changes to the extend_block in the new abs_data.work_area are lost. This might explain why an extension component of the work_area never gets released.
The abs_data structure for the outer-most script finally gets freed when the ec_input_ I/O switch is detached. The cleanup procedure in abs_io_.pl1 is finally called to release components of the extensible area, and free the outer-most abs_data structure.
clean_up:
procedure ();
declare p ptr;
if abs_data_ptr ^= null ()
then do;
if initialized
then do;
if abs_data.attach.save_ptr ^= null ()
then call iox_$destroy_iocb (abs_data.attach.save_ptr, status);
p = input_string.ptr; /* TEMP: this can be removed when terminate_noname is fixed */
input_string.ptr = null ();
if p ^= null () then call hcs_$terminate_noname (p, status);
call release_area_ (addr (abs_data.work_area));
end;
free abs_data;
end;
return;
end clean_up;
comment:5 by , 10 days ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
https://s3.amazonaws.com/eswenson-multics/public/mcrs/MCR10163.pdf.
Installed as MR12.9-1038.

To test my theory, I invoked the exec_com I was developing. For some reason, it went into a loop which created 4 more temp segments (for a total of 63 in use, and 2 free).
list_temp_segments 63 Segments, 2 Free !BBBKbcHFWxfwjm.temp.0305 command_processor_ !BBBKbcHFXHQmDB.temp.0362 emacs !BBBKbcHFXHWDLw.temp.0363 emacs !BBBKbcHFXQKWkm.temp.0433 emacs !BBBKbcHFXQKdqf.temp.0434 emacs !BBBKbcHFXQQQJQ.temp.0440 emacs !BBBKbcHFcglBfc.temp.0446 command_processor_ !BBBKbcHFcgzxdl.temp.0454 command_processor_ !BBBKbcHFchBGJp.temp.0455 command_processor_ !BBBKbcHFlpHmpB.temp.0457 ec_input_ (area) !BBBKbcHKLmmBGD.temp.0477 ec_input_ (area) !BBBKbcHKPddDbh.temp.0500 ec_input_ (area) !BBBKbcHKXgkmXL.temp.0501 ec_input_ (area) !BBBKbcHKhNnXgh.temp.0502 ec_input_ (area) !BBBKbcHKjQFcQd.temp.0503 ec_input_ (area) !BBBKbcHKmpMGcn.temp.0504 ec_input_ (area) !BBBKbcHKwWbkBW.temp.0505 ec_input_ (area) !BBBKbcHLHNqJkP.temp.0506 ec_input_ (area) !BBBKbcHLHPLQnn.temp.0507 ec_input_ (area) !BBBKbcHLHPLckF.temp.0510 ec_input_ (area) !BBBKbcHLKqFlCh.temp.0511 ec_input_ (area) !BBBKbcHLPCJbqp.temp.0512 ec_input_ (area) !BBBKbcHLgXlKfK.temp.0565 ec_input_ (area) !BBBKbcHLqdwQNd.temp.0566 ec_input_ (area) !BBBKbcHLqfNBMP.temp.0570 ec_input_ (area) !BBBKbcHMLDggcb.temp.0571 ec_input_ (area) !BBBKbcHMcGgMgg.temp.0572 ec_input_ (area) !BBBKbcHNQMKqkQ.temp.0573 ec_input_ (area) !BBBKbcHNZhbKXd.temp.0574 ec_input_ (area) !BBBKbcHNZhgHjJ.temp.0575 ec_input_ (area) !BBBKbcHNbzlfqj.temp.0576 ec_input_ (area) !BBBKbcHNbzqQFd.temp.0577 ec_input_ (area) !BBBKbcHNhfZpxl.temp.0600 ec_input_ (area) !BBBKbcHNhffjCx.temp.0601 ec_input_ (area) !BBBKbcHNlznBFG.temp.0602 ec_input_ (area) !BBBKbcHNlzwpKn.temp.0603 ec_input_ (area) !BBBKbcHNpCHmNb.temp.0604 ec_input_ (area) !BBBKbcHNpCPGCl.temp.0605 ec_input_ (area) !BBBKbcHPGWJCbh.temp.0606 ec_input_ (area) !BBBKbcHPGWNCQW.temp.0607 ec_input_ (area) !BBBKbcHPJJFzxB.temp.0610 ec_input_ (area) !BBBKbcHPJJKzpG.temp.0611 ec_input_ (area) !BBBKbcHPMbmlQf.temp.0612 ec_input_ (area) !BBBKbcHPMbwqnn.temp.0613 ec_input_ (area) !BBBKbcHPPNqQCD.temp.0614 ec_input_ (area) !BBBKbcHPPPBWHh.temp.0615 ec_input_ (area) !BBBKbcHPccZcpJ.temp.0616 ec_input_ (area) !BBBKbcHPccflDz.temp.0617 ring_zero_dump.1 (ring_zero_dump !BBBKbcHQBdpnJK.temp.0624 ring_zero_dump.1 (ring_zero_dump !BBBKbcHQgKCwQD.temp.0626 emacs !BBBKbcHWnjHwKP.temp.0625 ring_zero_dump.1 (ring_zero_dump !BBBKbcHWqwCdKj.temp.0627 ec_input_ (area) !BBBKbcHZBblQlQ.temp.0632 ec_input_ (area) !BBBKbcHZBblhmp.temp.0634 ec_input_ (area) !BBBKbcHZBblpnZ.temp.0635 ec_input_ (area) !BBBKbcHZBbwMxW.temp.0637 ec_input_ (area) !BBBKbcHZdwmzKC.temp.0647 ec_input_ (area) !BBBKbcHcfHpzwP.temp.0651 ec_input_ (area) !BBBKbcHcfHqxkD.temp.0650 ec_input_ (area) !BBBKbcHcfHwqzD.temp.0654 ec_input_ (area) !BBBKbcHcfHxpfl.temp.0655 ec_input_ (area)