1

In a rexx program, a COBOL program is invoked and it's SYSOUT is captured using a temporary dataset allocation (TSO alloc) and then using an EXECIO read. It works usually without any issues.

One of our users (using a different machine) reported an issue at the EXECIO read.

 IRX0562E Abnormal completion of the GET Data Management macro.   
 IRX0565E SG0     ,$LOGON  ,3420,D,SYSOUT  ,GET    ,WRNG.LEN.RECORD,0000003500000 0,QSAM.     
 IEC020I      001-4,SG0,$LOGON,SYSOUT,3420,BWS858,     
 IEC020I      SYS15089.T170858.RA000.SG0.R0278041     
 IEC020I DCB EROPT=ABE OR AN      INVALID CODE, AND/OR NO SYNAD EXIT  SPECIFIED   
 IRX0250E System abend code 001, reason code 00000004.     
 IRX0255E Abend in host command EXECIO or address environment routine MVS.

I found that this issue occured specifically when COBOL program has some outputs on SYSOUT. I could recreate similar situation in my z/OS system by specifying 'VB' attribute in TSO allocation. In this case, the allocated dataset is not viewable in ISPF. Following error message is shown, when trying to view it in ISPF.

'I/O error occurred reading the edit data'

If this corrupted data is allocated using SHARED/OLD mode then the problem is resolved. So this kind of issue occurs with New allocation and during the COBOL program execution.

After the COBOL program execution, further SHR/OLD mode allocation corrected this issue. Any ideas on what exactly went wrong here?

for the test version, I use the catalogued file as follows. The following allocation of SYSOUT, just before the COBOL program execution is as follows. See that the issue occurs only when I change the record format as 'VB'(which is a re-creation of same error reported by a user in another zos machine).


     if  (existsDSN(tmpDS)) then do  
         ADDRESS TSO,                        /* Here it works */
         "ALLOC DS('"tmpDS"') F(SYSOUT) SHR REUSE"  
     end  
     else do  
         ADDRESS TSO                        /* ds creation error here */   
         "ALLOC DS('"tmpDS"') F(SYSOUT) NEW DSORG(PS)",  
         "BLKSIZE(121) SPACE(5,15) TRACKS RECFM(F B A) DIR(0)"  
     end

please note that the catalogued SYSOUT dataset is not even readable in ISPF browse mode.


Following is the output of COBOL program mentioned by bill, however the first record appears twice(i.e, total 4 message lines) in SYSOUT.

 0000000121
4FFFFFFFFFF
00000000121
   '   ` expected message text
4070007004
00D0009000
cobp
  • 772
  • 1
  • 5
  • 19
  • You'd better show the rexx code. And the COBOL code which is involved with any DISPLAYs. – Bill Woodger Apr 01 '15 at 16:03
  • COBOL code is nothing special, usual display statement. But it seems like SYSOUT output should be compatible with FBA record format. REXX program has a TSO alloc command using ddname SYSOUT and space, RECFM parameters. – cobp Apr 02 '15 at 11:16
  • 1
    The error you are describing is that you have records on your file which do not match the description of the file, so the IO system thinks there has been an IO error. FBA vs FB would do it. The code may contain ordinary DISPLAY statements (how could it do other?) but I want to know if there are any unconditional ones. You're using the default DD SYSOUT for the DISPLAYs I imagine, is anything else you are doing also using that? There is of course the "try this" approach, but I don't care to just suggest something in the dark, unless I feel like it... – Bill Woodger Apr 02 '15 at 11:26
  • thanks for comments. It is default SYSOUT for those unconditional COBOL displays. As you remarked about it it is IO system conflict, but the interesting part is a second allocation(using SHR/OLD ) of this corrupted dataset resolves the issue. That means that SYSOUT dataset should be persistent to work it properly. – cobp Apr 02 '15 at 11:38
  • Not necessarily. Without seeing code, it is difficult (an understatement) to point to the reason. You may be "fixing" without knowing what the problem is. At the time when you rexx is reading the file, there is at least one record on that file which does not conform to the LRECL and/or RECFM. I'd catalog the file, abandon (a test version of) the rexx just before you access the file, and then run the catalogued file through something which can deal with RECFM=U, and you'll see *what* is causing the problem, then you'll have to locate *where* the problem is caused. Rats. There's "try this"... – Bill Woodger Apr 02 '15 at 11:54
  • Can you paste all the additional information into the question? Use the edit link beneath the question. – Bill Woodger Apr 02 '15 at 13:30
  • OK. Important now to see the whole rexx. – Bill Woodger Apr 02 '15 at 14:34
  • Can you describe in words what the output should be? To have an FBA, all the records should be the same length. In your first example, you have two records, which you have turned the HEX display on for, and the two records are different lengths (hence the problem when your program tries to read a "fixed-length" file). In your second example, you have a third length, one byte of data plus one bye (the leading one) of "carriage control". From the first run, check the characteristics (ISPF under option 3) of the dataset. Same for the second. Show the COBOL DISPLAY, the value of that variable, etc – Bill Woodger Apr 07 '15 at 08:53
  • Can you look at the latest update to my answer, and respond? – Bill Woodger Apr 07 '15 at 14:33
  • This is the syout of your program, STOB26. Line-1. is display of recordlength , so it is ok. Line-2 - Positions 2-8 contains some unexpected data, the remaining i mark it 'expected message text' is display from the COBOL program. Line-3 - content same as Line-1. Line-4 content same as Line-2. I think some issues with file ending as well. – cobp Apr 07 '15 at 16:08
  • Need to know what is in tmpDS. "Something else" is writing to, or has previous written to, that dataset. The reason it has done that is simply through the same name being used in more than one place. If you use a completely new name, unique to your Rexx program, and as long a you're not doing it in your Rexx, your program will run. The solution is to make your dataset names unique. Part of it, anyway. – Bill Woodger Apr 07 '15 at 22:52
  • You should always test the return from anything external in Rexx. You don't do this for your Allocates. You should. Just before the Allocate, put Trace R (or Trace I, if you prefer) and paste the result of the trace through to the failure. – Bill Woodger Apr 07 '15 at 22:54
  • `BLKSIZE(121) SPACE(5,15) TRACKS RECFM(F B A) DIR(0)` remove BLKISIZE(121) DIR(0) and the A from RECFM. Why SPACE (5,15)? Are you expecting *a lot* of output? – Bill Woodger Apr 07 '15 at 22:57
  • I've updated STOB26. Can you run the new one and paste the output, please. – Bill Woodger Apr 07 '15 at 22:58
  • 1) If you'd been able to show, or describe, your Rexx code, this would have been fixed on 1 April. 2) If you'd mentioned your suspicions, you'd have had confirmation. 3) Updated my answer to include how to change the use of DD SYSOUT from both COBOL and Language Environment. 4) You should update your answer (this one is an answer) to describe the relationship between DFSORT and COBOL in your Rexx which caused this problem. 5) I don't know for certain why, effectively, you ALLOC was giving you a "disposition" of MOD, I suspect something failed and you got a default. Always check RC. – Bill Woodger Apr 08 '15 at 10:01
  • I will update it later, but basically this is not just a TSO/REXX issue as intially thought, the same issue occur in batch mode as well. – cobp Apr 08 '15 at 16:30
  • OK, looking forward to that :-) You should make it a new question, this is tangled enough already. – Bill Woodger Apr 08 '15 at 16:32
  • Hopefully the last update to my answer. – Bill Woodger Apr 08 '15 at 21:30
  • It's a good signal for people reading these two questions in the future to Accept one or other of the answers. – Bill Woodger Apr 10 '15 at 15:20

2 Answers2

1

OK, so here is what the manuals say of your situation:

Enterprise COBOL Programming Guide

By default, DFSORT diagnostic messages are sent to the SYSOUT data set. If you want to change this default, use the MSGDDN parameter of the DFSORT OPTION control card or use the SORT-MESSAGE special register.

Enterprise COBOL Language Reference

You can use the SORT-MESSAGE special register to specify the ddname of a data set that the sort utility should use in place of the SYSOUT data set. The ddname specified in SORT-MESSAGE is equivalent to the name specified on the ’MSGDDN=’ control statement in the sort control file.

DFSORT Application Programming Guide (my emphasis)

//SYSOUT DD

Identifies the DFSORT message data set. The default ddname is SYSOUT, but you can specify an alternate ddname for the message data set using the MSGDDN installation or run-time option. Always supply a DD statement for the message data set if a catalogued procedure is not used. (If you are invoking DFSORT from a COBOL program and are using the ddname SYSOUT for the message data set, the use of DISPLAY in your COBOL program can produce uncertain printing results.)

DFSORT uses RECFM=FBA, LRECL=121, and the specified BLKSIZE for the message data set. If the BLKSIZE you specify is not a multiple of 121, DFSORT uses BLKSIZE=121. If you do not specify the BLKSIZE, DFSORT selects the block size as directed by the SDBMSG installation option (see z/OS DFSORT Installation and Customization). If you use a temporary or permanent message data set, it is best to specify a disposition of MOD to ensure you see all messages and control statements in the message data set.

And:

MSGDDN

MSGDDN=ddname

Temporarily overrides the MSGDDN installation option, which specifies an alternate ddname for the message data set. MSGDDN must be in effect if:

v A program that invokes DFSORT uses SYSOUT (for instance, COBOL uses SYSOUT) and you do not want DFSORT messages intermixed with the program messages.

v Your E15 and E35 routines are written in COBOL and you do not want DFSORT messages intermixed with the program messages.

v A program invokes DFSORT more than once and you want separate messages for each invocation of DFSORT.

The ddname can be any 1- through 8- character name but must be unique within the job step; do not use a name that is used by DFSORT (for example, SORTIN). If the ddname specified is not available at run-time, SYSOUT is used instead. For details on use of the message data set, see z/OS DFSORT Messages, Codes and Diagnosis Guide Note: MSGDDN is processed only if it is passed on the OPTION control statement in an extended parameter list or in DFSPARM.

What you have done, despite the advice in the manuals, is mix SYSOUT output from COBOL and DFSORT (indeed multiple invocations of DFSORT). You have done that whilst directing the SYSOUT to a sequential dataset, with different characteristics from that which DFSORT uses. Since DFSORT will always output messages, your dataset was guaranteed to be corrupted if the COBOL program used at least on DISPLAY in the run.

If you had directed the SYSOUT DD to a SYSOUT= (spool) dataset at any point during your testing (I'd guess close to 100% of people do it that way) you'd have noticed the mixed output on the SYSOUT dataset for that step. I'm not sure how it would have looked (having never done this, or known it to be done) but you would have been able to at least identify the source of the multiple use (the same COBOL program, doing its own DISPLAYs, and also doing multiple internal SORTs).


You have solved your problem by using DFSORT's MSGDD= to modify the default output DD (SYSOUT).

It is worth noting that you can also change the name of the DD used for COBOL DISPLAY, from its default (SYSOUT) to something else, with the compiler option OUTDD(somedd).

Language Environment also uses SYSOUT by default, but you can use the run-time option MSGFILE to modify that (LE run-time options can be set in various ways, consult the Language Environment documentation (I find the easiest to be a //CEEDOPT DD in the JCL for a batch program).

Ensuring that files which are allocated for one execution of a program from within a Rexx program are then de-allocated afterwards, and the datasetnames are not re-used is something to watch for every time. Ensure that you always check RC, whenever something can set an RC. Don't specify options on statements which are not required.


Here's your data as shown by you before I pasted it into your question, from the program I provided:

0000000121
4FFFFFFFFFF
00000000121
   '   ` expected message text
4070007004
00D0009000

Second attempt:

expected message text

44
00

I'm not sure what "expected message text" means, nor the "the first record appears twice", nor "total 4 message lines".

The data isn't lined up. In your question, I corrected the 0000000121 part, but not the other record.

Ignoring the "expected message text" you are showing two data-records, in "hexadecimal" format (SET HEX ON in SDSF if you are using that to browse spool output).

The first blank may be an artifact of SDSF. When you first look at a spool file, if you look at the COLS, you'll see that the data starts at column two. If you move your screen to the left, you'll then see the first column, which is not data.

So, we could guess that you actually have two records. One which is 10 zoned-decimal digits (or "character") and one which is very definitely not the same.

The first record looks like a fixed-length record, of 10 bytes. The second looks live a variable-length record. In fact, it is a block of variable-length data.

This file will, with absolute certainty, give you your "wrong length record".

However, even given that, there is something not quite right with what you show. I think that what you have done is not copy all the trailing blanks.

We know you have an LRECL of 121, and for fixed-length records, that means the records will be 121 bytes long, yet you show 10 bytes. OK, could be written from something overriding the length to 10.

However, for the variable-lenght data, it goes like this

X'007D' = block length, 125 bytes, first half of the Block Descriptor Word (BDW) including the length (four) of the BDW. X'0000' = second half of the BDW X'0079' = record length, 121 bytes, first half of the Record Descriptor Word (RDW) including the length (four) of the RDW. 121 bytes of data, which you show as X'40'. So let's assume 121 bytes of space.

Let's therefore go back and assumed that the fixed-length record is 121 bytes with trailing blanks. Seeing that in your "answer" the first "line" was not aligned, we can assume you made an adjustment for the leading blank, and also on the second record.

It is not yet clear from where, but your file is definitely "a mix". You have one fixed-length record, then one variable-length block (containing only one record) You need paste exactly what you see once you have selected the spool file the output is in hex mode. All the way from left to right of your screen. Copy/paste, not screenprint.

Which do you think is the correct line? The blanks, or the 0000000121?


OK, still not a lot to work on :-)

Your problem is with tmpDS. Can't see the content of that, but that is the problem.

It has a name that looks very temporary, but the content is making things much more permanent than you are expecting.

At the time the user who gets the failure is on your system and getting to the running of the COBOL program, the file, a dataset with that exact name, already exists on the system. COBOL is just going to blithely clobber it, probably with FBA 121. If the file being used previously was anything other than what COBOL clobbers it with, you will get the exact situation you detail.

There are multiple possibilities for how that has happened. Using the same name in different rexx programs is the easiest. Prefixing it with the TSO-userid may partly help, but you need to either let the system decide on the name or generate it yourself such that it cannot be duplicate.

Can't be certain of this without seeing your code. Only 99.3% sure, until you tell me otherwise :-)

Here's a short program you can use to read the file and see what is in there:

   ID DIVISION. 
   PROGRAM-ID. STOB26. 
   ENVIRONMENT DIVISION. 
   INPUT-OUTPUT SECTION. 
   FILE-CONTROL. 
       SELECT IN-FILE  ASSIGN TO INFILE 
       FILE STATUS IS W-FILE-STATUS. 
   DATA DIVISION. 
   FILE SECTION. 
   FD  IN-FILE 
       RECORD IS VARYING 
       DEPENDING ON W-REC-LENGTH 
       RECORDING MODE U. 
   01  IN-REC. 
       05  FILLER OCCURS 1 TO 32760 TIMES 
           DEPENDING ON W-REC-LENGTH       PIC X. 
   WORKING-STORAGE SECTION. 
   01  W-FILE-STATUS                       PIC XX. 
       88  FILE-STATUS-GOOD                VALUE "00". 
       88  FILE-STATUS-OK-FOR-INPUT        VALUE "00" "10".
       88  END-OF-FILE                     VALUE "10". 
   01  W-REC-LENGTH                        PIC 9(8) COMP. 
   PROCEDURE DIVISION.
       DISPLAY 'Start of program' 
       OPEN INPUT IN-FILE 
       IF NOT FILE-STATUS-GOOD 
           DISPLAY 
                   'OPEN FAILED' 
                   '>' 
                   W-FILE-STATUS 
                   '<' 
           CALL 'FRED' 
       END-IF 
       PERFORM UNTIL END-OF-FILE 
           READ IN-FILE 
           IF NOT FILE-STATUS-OK-FOR-INPUT 
               DISPLAY 
                       "READ FAILED" 
                       '>' 
                       W-FILE-STATUS 
                       '<' 
               CALL 'FRED' 
           END-IF 
           DISPLAY 
                   'Record length is>'
                   W-REC-LENGTH 
                   '<'
           DISPLAY 
                   'Data is>' 
                   IN-REC 
                   '<'
       END-PERFORM 
       CLOSE IN-FILE 
       IF NOT FILE-STATUS-GOOD 
           DISPLAY 
                   'CLOSE FAILED' 
                   '>' 
                   W-FILE-STATUS 
                   '<' 
           CALL 'FRED' 
       END-IF 
       DISPLAY 'End of program' 
       GOBACK 
       . 

The JCL is very simple, and can be based on this:

//RUNIT EXEC PGM=VARA,TIME=(,2)
//STEPLIB DD DSN=loadlibrary,DISP=SHR 
//SYSOUT DD SYSOUT=* 
//INFILE DD DSN=yourbusteddsn,LRECL=32760,RECFM=U,DISP=SHR
Bill Woodger
  • 12,968
  • 4
  • 38
  • 47
  • Thanks, I will check this on next working day, tuesday. – cobp Apr 02 '15 at 21:39
  • OK. We'd know for sure if we could see the code... so if it is wrong **PASTE THE CODE**, please? – Bill Woodger Apr 02 '15 at 22:08
  • I don't have net connection at the workplace. I could only post relevant portions of code, due to the rules enforced. – cobp Apr 03 '15 at 11:43
  • OK, fair enough. The relevant portions are the setting of and any amendment to the value of that variable, and any other programs used from that specific rexx program. – Bill Woodger Apr 03 '15 at 11:46
  • btw, There is a tricky way to correct it, without keeping cataloged temp. dataset as follows: 1.allocate new sysout dsn, 2. call cobol program,2.free sysout and allocate again using shr/old 3. call cobol program again and read sysout 4. delete syout dsn. Since the repeated calls does not impact final result, it works. – cobp Apr 03 '15 at 11:55
  • I only suggested keeping the dataset as a means of demonstrating that something else has written data to it, not as a permanent thing. Generating a unique name, or letting the system do it, and having it deleted after use is the best way. – Bill Woodger Apr 03 '15 at 12:18
0

As I suspected this has something to do with DFSORT sysout messages. After redirecting DFSORT messages to another dataset by specifying DFSPARM parameter, this problem got resolved. I could do this by allocating DFSPARM ddname which corresponds to a dataset that contains

  MSGDDN=dfsoutdd

This issue occurs in batchmode aswell, i.e, it has nothing to do with the TSO alloc, or rexx program. To summarize, the problem occurs when

  1. COBOL program has internal SORTS and thus produces DFSORT messages on SYSOUT
  2. COBOL program itself has a single /or more of text display
  3. When SYSOUT is directed to a DSN with DISP=NEW(SYSOUT on SDSF spool is OK)

One more observation is DFSORT causes Dataset attribute alteration after program execution. Before

Organization . . . : PS Used tracks . . . . : 1
Record format . . . : VB Used extents . . . : 1
Record length . . . : 121
Block size . . . . : 27998
1st extent tracks . : 1

After

Organization . . . : PS Used tracks . . . . : 1
Record format . . . : FBA Used extents . . . : 1
Record length . . . : 121
Block size . . . . : 121
1st extent tracks . : 1
Secondary tracks . : 1
cobp
  • 772
  • 1
  • 5
  • 19