[Asterisk-bsd] Re: [Asterisk-Dev] moh issues
Luigi Rizzo
rizzo at icir.org
Wed Jun 15 05:58:22 CDT 2005
On Wed, Jun 15, 2005 at 03:57:36AM -0700, Luigi Rizzo wrote:
> [background: i noticed a strange behaviour of asterisk on FreeBSD 4.11
> and userland pthreads library when using res_musiconhold.]
forgot the attachments :)
-------------- next part --------------
/*
* test descriptor issues on threads.
*
* compile with cc -o simple simple.c
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int
main(int argc, char *argv[])
{
pid_t p;
int fd[2];
FILE *f;
pipe(fd);
sleep(atoi(argv[1]));
dup2(fd[0], STDOUT_FILENO);
fcntl(0, F_SETFL, ~O_NONBLOCK & fcntl(0, F_GETFL));
fcntl(1, F_SETFL, ~O_NONBLOCK & fcntl(1, F_GETFL));
fcntl(2, F_SETFL, ~O_NONBLOCK & fcntl(2, F_GETFL));
sleep(atoi(argv[1]));
return 0;
}
-------------- next part --------------
/*
* test descriptor issues on threads.
*
* compile with cc -o thre -lc_r thre.c
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
int dump_desc(char *s, int w)
{
int i;
fprintf(stderr, "-- [pid %d thr %p] %s --\n", getpid(),
pthread_self(), s);
for (i=0; i<8; i++) {
fprintf(stderr, "fd %d flags 0x%lx (system 0x%lx)\n", i,
_thread_fd_getflags(i),
__sys_fcntl(i, F_GETFL));
}
sleep(w);
return 0;
}
int
main(int argc, char *argv[])
{
pid_t p;
int i, fd[2];
pipe(fd);
fprintf(stderr, "child-end %d parent end %d max %d\n",
fd[0], fd[1], getdtablesize());
dump_desc("start main", 0);
p = fork();
if (p == 0) { /* child */
/*
* close parent's end. It's a pipe so O_NONBLOCK remains.
* You can also do it in the loop below.
*/
close(fd[1]);
/*
* First tell libc_r to leave O_NONBLOCK on the descriptors
* even after a close() or exec(),
* _After_ that, close() all descriptors you don't need
* in the child, because they are shared and the child
* could change their mode in unexpected way causing us
* trouble.
* You can limit the loop (getdtablesize() is often large)
* but at least make sure to act on the descriptor you are
* using on the parent threads in blocking mode.
*/
if (argc > 1)
for (i=0; i < getdtablesize(); i++) {
long fl = fcntl(i, F_GETFL);
if (fl != -1 && i != fd[0]) {
/* open and must be closed in the child */
fcntl(i, F_SETFL, O_NONBLOCK | fl);
close(i);
}
}
dup2(fd[0], STDOUT_FILENO);
sleep(2);
/*
* now we can finally exec a process without risking
* trouble. The process will only play with its own
* side of the pipes, which is not shared by the parent
* and so any action on it does not change the status
* on the parent side.
* The example process below does some weird things
* with the descriptors, and we use it to show that it
* does not harm us.
*/
execl("./simple", "simple", "2", NULL);
} else { /* parent */
close(fd[0]); /* close child end of the pipe */
sleep(1);
dump_desc("parent", 2);
dump_desc("parent after exec done", 2);
dump_desc("parent after child fcntl", 2);
dump_desc("parent after child dead", 0);
}
return 0;
}
More information about the Asterisk-BSD
mailing list