|
Description
|
Customer had an issue where syslogd would die every few weeks.
The customer had a cron job which sigHUP to syslogd every hour.
Extensive investigation showed that syslogd died because it ran out of
virtual address space due to door service threads allocation 1Mb stacks.
The particular customer system heavily used syslogd with many concurrent door_calls.
Further investigation showed that the issue is that active door_calls within the server thread will cause new door service threads to be created if active during a fork1()
The issue appears to be due to the lwp_suspend()/lwp_resume() of the threads in door_return()
The following testcase reproduces the issue on
SunOS t2000-c 5.10 Generic_125100-07 sun4v sparc SUNW,Sun-Fire-T200
server.c [gcc -o server server.c -ldoor]
#include <sys/types.h>
#include <unistd.h>
#include <door.h>
char *DoorFileName = "testdoor";
extern int __nthreads();
static void
server(void *cookie, char *argp, size_t arg_size,
door_desc_t *dp, uint_t n)
{
(void) door_return(NULL, 0, NULL, 0);
}
main(int argc, char argv[]) {
int DoorFd;
if ((DoorFd = door_create(server, 0, DOOR_REFUSE_DESC)) < 0) {
perror("door create failed");
exit(1);
}
if (fattach(DoorFd, DoorFileName) < 0) {
perror("door attach failed");
exit(1);
}
while (1) {
sleep(2);
if ((argc > 1) && fork1() == 0) {
sleep(1);
exit(0);
}
printf("current threads = %d\n", __nthreads());
}
}
knockdoor.c [gcc -o knockdoor knockdoor.c -ldoor]
#include <fcntl.h>
#include <thread.h>
#include <sys/types.h>
#include <unistd.h>
#include <door.h>
char *DoorFileName = "testdoor";
void *knockdoor(void * a) {
int d;
int s;
door_arg_t darg;
door_info_t info;
while (1) {
if ((d = open(DoorFileName, O_RDONLY)) < 0)
return (0);
darg.data_ptr = NULL;
darg.data_size = 0;
darg.desc_ptr = NULL;
darg.desc_num = 0;
darg.rbuf = NULL;
darg.rsize = 0;
s = __door_call(d, &darg);
close(d);
}
}
main(int argc, char argv[]) {
int i;
for (i = 0; i < 100; i++) {
int tid;
thr_create(NULL, 0, knockdoor, NULL, THR_DETACHED, &tid);
}
while (1) sleep(1);
}
------------------------------------------
rm testdoor; touch testdoor
./server fork &
./knockdoor &
server will run serviceing door_calls and fork1() every couple of seconds;
knockdoor will create 100 threads/lwps which loop doing door_calls.
we see the number of threads within server steady if we dont do fork1()
but increasing everytime we do fork1().
|