#include <ncpx_app.h>int NCPX_DetachForkedChildFromServer(void);
In the forked child, this call should be immediately followed by a call to exec(2).
NCPX handlers are allowed to fork and create independent child processes, but these child processes are not allowed to maintain any association with the server.
When a handler forks, the child inherits all of the parent's attachments and associations with the NWS server (shared memory, open files, signal disposition, and so on). If these associations are not removed by detaching the child process from the server, the child prevents the server from going down.
To detach the forked child from the server, the forked child must call NCPX_DetachForkedChildFromServer -- this is not an optional step.
This library routine detaches the forked child process from the NWS server and allows the child process to continue running after the server is shut down. This functionality should be used whenever an NCPX Handler needs to fork off independent processes.
BYTE run_app(NCPExtensionClientclient, void
requestData, LONG requestDataLength, void
replyData, LONG
replyDataLength) { pid_t pid; struct sigaction action; char
command;
/* Set signal action stuff so child processes don't become zombies * AND we don't get SIGCHLD when child processes stop and continue. */
/* First get old action information. */ if ( sigaction( SIGCHLD, NULL, &action)) { printf("run_app: sigaction() error (get), errno %d\n", errno); return 0xff; } action.sa_flags |= SA_NOCLDWAIT; /* Prevent child processes from becoming zombies. */ action.sa_flags |= SA_NOCLDSTOP; /* Don't notify us on child stop/continue. */ if ( sigaction( SIGCHLD, &action, NULL)) { printf("run_app: sigaction() error (set), errno %d\n", errno); return 0xff; }
/* Since parent isn't going to wait around for the child to finish, * we can't depend on requestData being valid in the child (since the * parent will cause the buffer to be reused immediately). * So we have to make a copy of any data we're passing to the child * here, BEFORE the fork(). */ command = strdup( requestData); if ( command == NULL) { return 0xff; /* failure to dup() the command line. */ }
pid = fork(); if ( pid == -1) { free( command); return 0xff; /* Failure to fork. */ } if ( pid != 0) { /* Parent. */ free( command); /* Get rid of unneeded-in-parent command-line copy. */ return 0; }
/* Else we're the child. */
/* Detach from the server environment */ NCPX_DetachForkedChildFromServer();
/* Become session leader (detach from parent). */ if ( setsid() == -1) { printf("setsid() failure, errno %d\n", errno); } execlp( command, command, NULL); /* Shouldn't return */
/* Exit with error code if execlp returns. */ exit( 1);
}