Bug 26705

Summary: P_ALTSTACK in proc::p_flag isn't copied to the child process on fork(2)
Product: Base System Reporter: fwkg7679 <fwkg7679>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description fwkg7679 2001-04-19 16:00:01 UTC
P_ALTSTACK in struct proc::p_flag should be copied to the child process on fork(2),
but actually it isn't.  The setting of the signal stack by sigaltstack(2) on the parent 
process is not inherited to the child process on fork(2) as a result of this problem.
This causes a fatal problem on Pthreads applications that uses fork(2).

The manpage of sigaction(2) states that the signal stack is inherited to the child process
but the signal stack isn't inherited on 4-STABLE and 5-CURRENT.  On 3-STABLE systems,
the signal stack seems to be inherited to the child process correctly.

For more information, please read these mails in -current list:
  http://docs.freebsd.org/cgi/getmsg.cgi?fetch=473293+0+archive/2001/freebsd-current/20010318.freebsd-current
  http://docs.freebsd.org/cgi/getmsg.cgi?fetch=332928+0+archive/2001/freebsd-current/20010304.freebsd-current

Fix: Apply this patch to kernel sources:
How-To-Repeat: Run the following program and compare the result on other operatiing systems.
At least, FreeBSD 3-STABLE and NetBSD 1.5 correctly handles the setting of 
the signal stack.

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <assert.h>

#define ALTSTACKSIZE	(1024 * 1024)
static u_int64_t	altstack[ALTSTACKSIZE / sizeof(u_int64_t)];

static void
print_sigstack(char *info)
{
	struct sigaltstack		ss;
	int				ret;

	ret = sigaltstack(NULL, &ss);
	if (ret < 0) {
		perror("sigaltstack");
		exit(1);
	}
	printf("%10s: sp=%p size=%d flags=%x\n",
	       info, ss.ss_sp, ss.ss_size, ss.ss_flags);
	fflush(stdout);
}

int
main(int argc, char *argv[])
{
	struct sigaltstack		ss;
	pid_t				pid;
	int				ret;

	print_sigstack("original");

	ss.ss_sp = (char *)altstack;
	ss.ss_size = sizeof(altstack);
	ss.ss_flags = 0;
	ret = sigaltstack(&ss, NULL);
	if (ret < 0) {
		perror("sigaltstack");
		exit(1);
	}
	print_sigstack("changed");

	pid = fork();
	if (pid < 0) {
		perror("fork");
		exit(1);
	}
	if (pid == 0) {
		print_sigstack("child");
		exit(0);
	}
	wait(NULL);
	print_sigstack("parent");

	return 0;
}
Comment 1 Akinori MUSHA freebsd_committer freebsd_triage 2001-05-07 19:08:58 UTC
State Changed
From-To: open->closed

Committed in 5-CURRENT and will be MFC'ed to 4-STABLE in 3 days. 

Thanks for the detailed report and the patch!