-1

I was trying to create a child process using fork but it is repeatedly returning -1, I tried to found the causes and I came to this:

Fork() will fail and no child process will be created if:
[EAGAIN]           The system-imposed limit on the total number of pro-
                   cesses under execution would be exceeded.  This limit
                   is configuration-dependent.

[EAGAIN]           The system-imposed limit MAXUPRC (<sys/param.h>) on the
                   total number of processes under execution by a single
                   user would be exceeded.

[ENOMEM]           There is insufficient swap space for the new process. 

Now I don't know how to check the first and third point but on looking at point MAXUPRC - I looked into sys/param.h:

//<sys/param.h>
#define MAXUPRC     CHILD_MAX   /* max simultaneous processes */

CHILD_MAX has been mentioned here (unistd.h):

//<unistd.h> - DEFINED IN MY SYSTEM
#define _SC_CHILD_MAX            2 

CHILD_MAX - _SC_CHILD_MAX The maximum number of simultaneous processes per user ID. Must not be less than _POSIX_CHILD_MAX (25).

Now I can't establish if keeping _SC_CHILD_MAX less than 25 is the reason or do I have to look into 1st and 3rd causes (they are hard to check as the system is Z/OS with limited access and I don't have much idea about it).

perror(""); isn't printing anything and errno is printing 655360.

  #include<stdio.h>
  #include<errno.h>
  #include<unistd.h>
  #include<stdlib.h>

   int main()
   {
       long int prc_id;

       prc_id=fork();

       if(prc_id ==0)
          calling_child();        
       else if(prc_id <0)
       {
           printf("errno - %d\n",errno); 
           printf("failed %d\n",prc_id);
           exit(0);
       }

      return 0;
 }

This above code runs fine and creates a child process on my own laptop (centos) but in dev environment I guess there are some restrictions.

calling_child is never called as the prc_id returned is -1 (not even first print statement is printed on entering the function).

Agrudge Amicus
  • 1,033
  • 7
  • 19
  • Just a few other points that might help you. First, all the errno/errno2 values are defined in a book called "z/OS UNIX System Services: Messages and Codes". You'll have better luck if you use "printf("Error %x/%x - %s", errno, __errno2(), strerror(errno))" or something similar immediately after encountering a problem (remember, many library functions reset errno, so you need to reference it soon as an error occurs). Also, since the document I referred you to lists errno's in hex, it's usually better to print them with "%x". – Valerie R Aug 07 '19 at 23:25
  • Process limits are concurrent running processes, not a cumulative value. The "ps" command tells you what you have running, and I've never seen a z/OS system configured with less than 25 processes/user. The setting comes from the UNIX Services configuration file - something like SYS1.PARMLIB(BPXPRM00). In there, MAXPROCSYS (systemwide process limit) and MAXPROCUSER (max processes per user) are key. It's also possible to override these values on a user-by-user basis if needs be. If you have access to a z/OS operator console, the "D OMVS,LIMITS" command will tell you the current settings. – Valerie R Aug 07 '19 at 23:41

2 Answers2

3

I copied your sample program to my z/OS system running z/OS Version 2.3, with a minor enhancement since you left out the calling_child function (UPDATED to add the sysconf() value for SC_MAX_CHILD):

  #include<stdio.h>
  #include<errno.h>
  #include<unistd.h>
  #include<stdlib.h>

   int main()
   {
       long int prc_id;
       printf("SC_CHILD_MAX = %d\n", sysconf(_SC_CHILD_MAX));

       prc_id=fork();

       if(prc_id ==0)
          calling_child();        
       else if(prc_id <0)
       {
           printf("errno - %d\n",errno); 
           printf("failed %d\n",prc_id);
           exit(0);
       }

      return 0;
     } 

   static void calling_child(void)
   {
      printf("Hello from PID %x\n", getpid());
      return;
   }

I put the code in a file called test2.c and built it with this shell command: c99 -o test2 -g test2.c

It compiles cleanly and I was able to run it with no problems. It produces this output:

SC_CHILD_MAX = 32767
Hello from PID 40100b2

Most likely your build or execution environment isn't configured properly. It absolutely works fine on my pretty basic system, and I didn't have to do anything unusual at all to get it running.

A few small hints...

How are you getting into the z/OS UNIX shell? If you're logging onto TSO then running the ISPF shell or the OMVS command, you might prefer simply SSH'ing into your z/OS system. I usually find this is the cleanest batch environment.

Second thing is that you probably want to double-check your C/C++ environment. There are some good debugging features built into the IBM XLC compiler - try man C99 (or whatever dialect you use) and have a read.

Third thing is that IBM includes the dbx debugger in z/OS, so if you really get stuck, just try running your executable under dbx and you can step through your program line at a time.

As for those ERRNOs and so on, don't forget to also look at the __errno2() values - they usually have a very specific reason code that goes along with the more generic errors. For example, your z/OS security administrator can certainly do things to limit your use of z/OS UNIX functions - that would be revealed in the __errno2() values pretty clearly.

Stick with it though - if you know UNIX or Linux, all the skills you have from using the shell to coding pretty much transfer 100% to z/OS if you put in a little time to learning the basics.

Valerie R
  • 1,769
  • 9
  • 29
  • Please go into `sys1.sceeh.sys.h` and check what value has been set for `_SC_CHILD_MAX` – Agrudge Amicus Aug 07 '19 at 20:06
  • I believe you might be misunderstanding the use of _SC_CHILD_MAX. – Valerie R Aug 07 '19 at 23:01
  • There is a big problem in this --> in unix shell (to be precise in /etc/profile) -> line `for _CMP in _C89 _CC _CXX; do` is commented and I don't have edit permission to un-comment it due to which on compiling a file I am getting `IKJ56228I DATA SET CEE.SCEELKEX NOT IN CATALOG OR CATALOG CAN NOT BE ACCESSED` error & I can't test in unix environment. Though MAXPROCSYS is 4096 and MAXPROCUSER is 2048 – Agrudge Amicus Aug 09 '19 at 10:11
  • Here are the other values: `sysconf(_SC_MAX_CHILD)` -> -1, `errno --> a0000 errno2 --> c10f0001` ------------- This is when the code is run in the non-unix environment. – Agrudge Amicus Aug 09 '19 at 15:00
  • A glance through IBM's "z/OS UNIX Services Messages and Codes" reveals that there is no error of "a000" and no errno2 of c10f0001, so there's something more dramatic going on here. – Valerie R Aug 12 '19 at 22:27
  • How are you compiling your code if you can't run the compiler due to the problems you mention? If you're running the compiler in batch, there are a variety of options you need when generating code for the UNIX environment. You may need other environment variables set if your site isn't configured normally: STEPLIB pointing to the CEE datasets (these are the C/C++ runtime libraries, by the way). Or, perhaps your organization doesn't actually license the IBM XLC product...there should be messages on the z/OS console indicating the problem in more detail - ask your z/OS person for help. – Valerie R Aug 12 '19 at 22:39
-2

If you've been playing with fork(2) you may well have used up your limit of processes available to your process, see ulimit for your shell:

$ help ulimit | grep process
Ulimit provides control over the resources available to processes
    -d      the maximum size of a process's data segment
    -l      the maximum size a process may lock into memory
    -u      the maximum number of user processes

If so, logging out and logging back in again will solve the problem.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
James K. Lowden
  • 7,574
  • 1
  • 16
  • 31
  • I don't think it can be run on Z/OS – Agrudge Amicus Aug 07 '19 at 17:38
  • @Joshua, he could have 1 process left. From the shell, invoking the compiler uses that process. All OK. Then he runs his program, which he can also launch, just like he could launch the compiler. Then it calls fork(2), and fails. – James K. Lowden Aug 07 '19 at 19:10
  • @AgrudgeAmicus, IBM seems to think z/OS has fork: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/com.ibm.zos.v2r3.bpxbd00/rtfor.htm. If not, his system is seriously misconfigured with header files and libraries for unsupported system calls. – James K. Lowden Aug 07 '19 at 19:12
  • @JamesK.Lowden System has `fork` in some current running file - I think your point related to 2 processes is right and I was somewhat thinking on the same lines. But there is another file which uses `fork` with `pthreads` - I guess that thread system makes difference. – Agrudge Amicus Aug 07 '19 at 19:23
  • @JamesK.Lowden: Nope! `cc` invokes `ld`. They gotta have at least two to compile. – Joshua Aug 07 '19 at 19:57
  • @Joshua On setting `rlim_max` as 1 (not 2) the compilation take place successfully on `gcc 8.3 - centos`. though `fork()` fails. – Agrudge Amicus Aug 07 '19 at 20:34
  • @Joshua check the link: https://stackoverflow.com/questions/32649829/setting-low-rlimit-nproc-value-doesnt-allow-even-a-single-fork I have run the code using a non-root user access. – Agrudge Amicus Aug 07 '19 at 20:38