How to abend job intentionally - cobol

Is it possible to abend your job intentionally through COBOL program.
suppose I have an Input file having Header,Detail and Trailer records. I will write a COBOL pgm which reads this file.If no Detail records are found in this file then I want to abend my job by giving some Abend Message and some Abend Code.Is it Possible?

Do you want to ABEND your program or just set a RETURN-CODE?
I suspect setting a RETURN-CODE, writing a message
and then terminating the program via a STOP RUN or GOBACK is all that
you really want to do. Causing an actual ABEND may not be necessary.
In an IBM batch environment, the RETURN-CODE set by your program becomes the
RC for the JCL job step the program was run under. This is typically what you
want to set and test for.
The RETURN-CODE is set by MOVEing a numeric value to it. For example:
DISPLAY 'No Detail Records found in file.'
MOVE 16 TO RETURN-CODE
GOBACK.
You may also issue a program dump from a program run under Language Environment (IBM
Mainframe option) using
the CEE3DMP--Generate dump
utility.
In older IBM Mainframe COBOL programs, you might see calls to the ILBOABN0 routine. This call
abended your program and issued a dump. This routine is now depreciated in favour of the
technique outlined above.
Finally, really old programs might have code in them to generate abends. This can be done in any number of ways, but division by zero was
often a favourite:
DIVIDE SOME-NUMBER BY ZERO GIVING SOME-NUMBER.
Works every time!
Personally, I recommend setting the RETURN-CODE over calling ILBOABN0 or data-exception tehcniques.
Note: The RETURN-CODE special-register is not part of the COBOL-85 standard. It is available as an IBM extention to the language. You may need to resort to a different mechanism if you are working in a non-IBM compatible environment.

see the following link on how to set the return code passed back to a JCL job step as well as force an Abened code.
http://www.tek-tips.com/viewthread.cfm?qid=1058302&page=22

First, you should check what is accepted by your own shop's/site's working standards. Most teams will already have an accepted way to deliberately abend a program for a 'logic' reason. One company I worked at has a very simple program called SYSABND2, which I believe is written in assembler, which is called just to abend the program.
That said, to ABEND (not just set return code), you should call module CEE3ABD (or previous version ILBOABN0, which is now deprecated).
For details, see:
https://www.ibm.com/support/knowledgecenter/SSLTBW_2.4.0/com.ibm.zos.v2r4.ceea300/clcdump.htm
http://publib.boulder.ibm.com/infocenter/zvm/v5r4/index.jsp?topic=/com.ibm.zos.r9.ceea400/ceea4150320.htm

One method for doing an abnormal end of run is to output a message to the user terminal or to the operator at a mainframe computer centre and possibly to a printer if necessary, all depending on the type of computer the program is to be run on. In cobol it is possible to use DISPLAY UPON .. and use an identifier for the terminal, operator console, or printer as defined in an entry in the SPECIAL-NAMES section of the ENVIRONMENT DIVISION. An example may be similar to this using the correct device names for your case
OPERATOR-CONSOLE IS OUT-OP2 in special-names with DISPLAY "RUN ERROR - NO DETAIL RECORDS, ABORTING" UPON OUT-OP2 and
DISPLAY "REPORT TO OPERATIONS MANAGER" UPON OUT-OP2 and STOP RUN. in procedure division.
A reference to the circumstance would need to be included in any job or macro and operating instructions.

Yes, it is possible to abend your job intentionally through COBOL program by simply calling one module which doesn't exist. It will give S806 abend code.

Related

Mainframe CEE3DD abend - CEE3501S - Module not found in COBOL Dynamic Call

I have encountered an issue recently while processing a CICS transaction. My CICS transaction is calling a chain of dynamically linked COBOL modules. The transaction runs fine for the first time after the PGM-A load is new copied into the region. When I try to process the transaction for the second time, I keep getting CEE3DD abend saying the module not found for PGM-B which is being called from PGM-A. IF I do a new copy for PGM-A in CICS, the transaction again runs fine.
Something is wrong with the CICS setup or memory but I am not able to figure it out. PGM-A is working fine in batch processing. PGM-B has no issues when it is called from any other PGMs except PGM-A.
Can someone share some thoughts on what may be wrong with this?
To invoke your program via CICS, it must be compiled with the NODYNAM option.
It admittedly seems counter-intuitive, but using the DYNAM option will cause CICS stubs to be loaded, instead of your intended programs, and result in the CEE3501S condition.
So, compile your programs with the NODYNAM option to avoid this error condition.
See the following links for additional info:
https://www.ibm.com/support/knowledgecenter/en/SSGMCP_5.3.0/com.ibm.cics.ts.applicationprogramming.doc/topics/dfhp3_cobol_subprog_rules.html
http://www-01.ibm.com/support/docview.wss?uid=swg21054079
Does PGM-A use "CALL VARIABLE" to invoke PGM-B? If so check the contents of VARIABLE on the second run (the contents of that variable will probably be reported in the error message. The contents of the variable may be overwritten by a bug in PGM-A. That might explain why the program always fails after the (seemingly) succesful run and after a newcopy.
Converting this from dynamic to static worked. But the question remains why it was not working with dynamic linking.

run-time evaluation of values in DelphiWebScript

My delphi application runs scripts using JvInterpreter (from the Jedi project).
A feature I use is runtime evaluation of expressions.
Script Example:
[...]
ShowMessage(X_SomeName);
[...]
JvInterpreter doesn't know X_SomeName.
When X_SomeName's value is required the scripter calls its OnGetValue-callback.
This points to a function I handle. There I lookup X_SomeName's value and return it.
Then JvInterpreter calls ShowMessage with the value I provided.
Now I consider switching to DelphiWebScript since it has a proper debug-interface and should also be faster than JvInterpreter.
Problem: I didn't find any obvious way to implement what JvInterpreter does with its OnGetValue/OnSetValue functions, though.
X_SomeName should be considered (and actually is, most of the time) a variable which is handled by the host application.
Any Ideas?
Thanks!
You can do that through the language extension mechanism, which has a FindUnknownName method that allows to register symbols on the spot.
It is used in the asm lib module demo, and you can also check the new "AutoExternalValues" test case in ULanguageExtensionTests, which should be closer to what you're after.

Is each source line address in a detailed MAP file a valid address to insert a Int3h?

I am trying to create a code coverage tool using Delphi 2007.
My general approach is to use the Win32 Debug API to insert breakpoints for each source line and then remove the breakpoints as I pass them - thus I would be able to track each executed source line.
Outline of my approach:
parse the detailed MAP file (as generated by Delphi 2007) to find all the addresses for each source line (only for .text segments)
open the application in debug mode using the OpenProcess API call
iterate over each source line and insert an Int3 instruction (one $cc byte using WriteProcessMemory + FlushInstructionCache) at the address of each line
continue executing and as each breakpoint is triggered, remove the corresponding breakpoint and mark the line as covered
After either each breakpoint is passed or program exists I generate a report on what lines were covered and which lines were not for each source module
Now on to my question:
Is each source line address in a detailed MAP file a valid address to insert an Int3 breakpoint?
While the approach was successful for some simple units, I run in to access violations for some larger applications where the violated address includes a $cc - which would lead me to think that my approach needs some modification to work.
Hints on better approaches also very welcome!
Well, in theory: yes. And practical, I think yes too. If Delphi can place a breakpoint on every line, so can you :-).
Probably you need some specific handling for some case (for example: first line of a procedure is initialization of local vars, setting EBP etc).
So can you find out in which case it fails?
Btw: nice project! Is it open source?
P.S. if you need some assembly code handling: look at koldetours.pas (use google search).

External stored procedure on IBM i

I am trying to create an external stored procedure on an IBM i (V5R4), but I'm getting an error when I try to run it.
All I want to do is call an RPG program, without passing any parameters or worrying about returning any data. Sorry, I'm not an RPG programmer or an expert on IBM i, so I could be missing something very simple.
The SQL to create the procedure:
CREATE PROCEDURE SOMELIB.SOMEPROC ( )
LANGUAGE RPGLE
NOT DETERMINISTIC
NO SQL
EXTERNAL NAME 'OTHERLIB/SOMERG'
PARAMETER STYLE GENERAL;
The error I get when executing CALL SOMELIB.SOMEPROC() is:
SQL State: 38501
Vendor Code: -443
Message: [CEE9901] Application error. RNX1216 unmonitored by BB1002RG at statement 2100000001, instruction X'0000'. Cause . . . . . : The application ended abnormally because an exception occurred and was not handled. The name of the program to which the unhandled exception is sent is SOMERG SOMERG . The program was stopped at the high-level language statement number(s) at the time the message was sent. If more than one statement number is shown, the program is an optimized ILE program. Optimization does not allow a single statement number to be determined. If *N is shown as a value, it means the real value was not available. Recovery . . . : See the low level messages previously listed to locate the cause of the exception. Correct any errors, and then try the request again.
Your procedure is calling the RPG program without the library list set. You can do one of two things:
1) Change the F-spec in the RPG program to qualify the library using the EXTFILE keyword.
2) Call a CL program from the stored procedure that adds the appropriate library to the library list making sure to allow for the fact that the library may already be there from a prior call. Then have the CL program call the RPG program.
(a little bit more rude solution) Identify the user that starts the Stored Procedure. Change the jobdescription of that user to have the correct library list.
But in my experience is the CL program the most pragmatic solution too.
Assuming the file is in the same library as the program, add EXTFILE(variablename) and USROPN to the F-spec. Take the library name from the PSDS and construct the variablename value before you OPEN the file.
If the file and program are in different libraries, you might create a data area in the program library to hold the name of the data library. Retrieve the data area (using the PSDS) instead of using the PSDS (for the file library). If program and file aren't kept together, it can be a good idea to keep the data library name in an external object that can be changed rather than recompiling.
(Actually, I've rarely used data areas in the past ten years or so. Instead I create a user index. Each entry in the *USRIDX replaces a data area. The entries are keyed by a value that used to be a data area name. One object replaces many others and one procedure can manage all entries. One object to own and authorize reduces some system overhead.)
A suggestion to get rid of this trouble: make the user profile JOBD contains all libraries needed by the stored procedure.

Sleep from within an Informix SPL procedure

What's the best way to do the semantic equivalent of the traditional sleep() system call from within an Informix SPL routine? In other words, simply "pause" for N seconds (or milliseconds or whatever, but seconds are fine). I'm looking for a solution that does not involve linking some new (perhaps written by me) C code or other library into the Informix server. This has to be something I can do purely from SPL. A solution for IDS 10 or 11 would be fine.
#RET - The "obvious" answer wasn't obvious to me! I didn't know about the SYSTEM command. Thank you! (And yes, I'm the guy you think I am.)
Yes, it's for debugging purposes only. Unfortunately, CURRENT within an SPL will always return the same value, set at the entry to the call:
"any call to CURRENT from inside the SPL function that an EXECUTE FUNCTION (or EXECUTE PROCEDURE) statement invokes returns the value of the system clock when the SPL function starts."
—IBM Informix Guide to SQL
Wrapping CURRENT in its own subroutine does not help. You do get a different answer on the first call to your wrapper (provided you're using YEAR TO FRACTION(5) or some other type with high enough resolution to show the the difference) but then you get that same value back on every single subsequent call, which ensures that any sort of loop will never terminate.
There must be some good reason you're not wanting the obvious answer:
SYSTEM "sleep 5". If all you're wanting is for the SPL to pause while you check various values etc, here are a couple of thoughts (all of which are utter hacks, of course):
Make the TRACE FILE a named pipe (assuming Unix back-end), so it blocks until you choose to read from it, or
Create another table that your SPL polls for a particular entry from a WHILE loop, and insert said row from elsewhere (horribly inefficient)
Make SET LOCK MODE your friend: execute "SET LOCK MODE TO WAIT n" and deliberately requery a table you're already holding a cursor open on. You'll need to wrap this in an EXCEPTION handler, of course.
Hope that is some help (and if you're the same JS of Ars and Rose::DB fame, it's the least I could do ;-)
I'm aware that the answer is too late. However I've recently encountered the same problem and this site shows as the first one. So it is beneficial for other people to place new anwser here.
Perfect solution was found by Eric Herber and published in April 2012 here: How to sleep (or yield) for a fixed time in a stored procedure
Unfortunately this site is down.
His solution is to use following function:
integer sysadmin:yieldn( integer nseconds )
I assume that you want this "pause" for debugging purposes, otherwise think about it, you'll always have some better tasks to do for your server than sleep ...
A suggestion: Maybe you could get CURRENT, add it a few seconds ( let mytimestamp ) then in a while loop select CURRENT while CURRENT <= mytimestamp . I've no informix setup around my desk to try it, so you'll have to figure the correct syntax. Again, do not put such a hack on a production server. You've been warned :D
Then you'll have to warp CURRENT in another function that you'll call from the first (but this is a hack on the previous hack ...).

Resources