The clue is that pressing ctrl-c generates a new prompt under the shell. I wrote a program to parse stdin, and print out each character in hexadecimal. The code for control C is not passed through the PTY -- hence the pty was generating the signal after all, the shell was detecting it; but the subprocesses weren't terminating.
The problem turned out to be that since shells inherit the signal action (sigaction) of their parent process, one must check or reset the signals before launching a new shell; and on the embedded device (sony PRS900) -- the default action for SIGINT and many other signals had been changed to SA_IGN (ignore).
So, one simply needs to add some code to the session.c program to initialize all signals to their default action, and then enable all of them. That will solve the problem, and the interrupts will function properly.
A complete copy of the session program follows; it will create a new session, set all signals to default values and enable them, and it will then exec a program of your choice...
// A program to create a new Linux session connecting to a specified terminal,
// and then execing a program.
// Written by Andrew Robinson of Scappoose Oregon.
// Released under (C) 2014, GPL v3
// https://www.gnu.org/copyleft/gpl.html
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
int main(int narg, char * const argv[] ) {
pid_t session;
char *const cmd = argv[2];
char *const *args = argv+2;
if (narg<3) {
fprintf(stderr,
"Usage: %s new_tty program [params]\n", argv[0] );
return 1;
}
session=fork();
if (session<0) return session;
if (session) {
int status;
printf("Session pid %d exited\n", waitpid( session, &status, 0 ) );
return status;
}
// Child falls through to here... print the sessionID.
{ // Signal handling is all to be set to defaults.
// INT should then terminate subprocesses of the shell.
sigset_t mask;
struct sigaction act;
int i;
// set all signals to the default action.
sigemptyset( &act.sa_mask );
act.sa_handler=SIG_DFL;
act.sa_flags=0;
for(i=1; i< _NSIG-1; ++i ) // Iterate over all signals.
sigaction( i, &act, NULL ); // Set action to default.
// enable all signals.
sigprocmask( SIG_SETMASK, &mask, NULL );
sigprocmask( 0,NULL,&mask );
if (!sigismember(&mask,SIGINT)) printf("SIGINT enabled\n");
}
session=setsid(); // make a session leader.
if (session<0) {
perror("bad-session:");
}
printf("%d\n", (int)session );
fflush(stdout);
close(0); close(1); close(2); // Close all IO to allow for a new CTTY.
open( argv[1], O_RDONLY ); // stdin
open( argv[1], O_WRONLY ); // stdout
open( argv[1], O_WRONLY ); // stderr
ioctl( 0, TIOCSCTTY, 0 ); // Set the controlling TTY based on stdin
return execvp( cmd, args );
}