Eyal Lebedinsky
2003-12-02 19:46:34 UTC
I am trying to undersnatd the interaction between threads and
exec(). The attached program demonstrates how the exec() behaves
differently when issued from inside a thread (./p) or directly
from main (./p x). In the former case the shell proceeds when
the exec is issued rather than wait for the completion of the
program.
The problem is that the exec'ed program takes over the pid of
the thread rather than of main(), and the original process
exits, letting my shell proceed rather than wait.
How do I prevent this? I have a need to exec() from inside a
thread and not release a wait()ing parent at that point.
I tried playing with pthread_attr_setscope() but got incorrect
results: non-zero return code and no perror. Just change to
PTHREAD_SCOPE_PROCESS
and see. Anyway, it probably is unrelated.
I looked into process groups and got no solution either.
--
Eyal Lebedinsky (***@eyal.emu.id.au) <http://samba.org/eyal/>
-------------- next part --------------
#include <stdio.h>
#include <sys/types.h> /* pid_t */
#include <unistd.h>
#include <pthread.h>
static pid_t main_pid;
static pid_t main_pgrp;
static pid_t thread_pid;
static pid_t thread_pgrp;
void
check (char *func, int rc)
{
if (rc) {
fprintf (stderr, "%s rc=%d", func, rc);
perror (" ");
exit (1);
}
}
void *
thread (void *parm)
{
thread_pid = getpid ();
thread_pgrp = getpgrp ();
fprintf (stderr,
"thread pid is %ld pgrp is %ld\n",
(long)thread_pid,
(long)thread_pgrp);
execl ("/bin/sh", "sh", "-c", "(sleep 1 ; echo hi from $$)", NULL);
/* not reached */
return (NULL);
}
int
main (int argc, char **argv, char **envp)
{
pthread_attr_t attr;
pthread_t th;
void *rc;
main_pid = getpid ();
main_pgrp = getpgrp ();
fprintf (stderr,
"main pid is %ld pgrp is %ld\n",
(long)main_pid,
(long)main_pgrp);
if (argc > 1)
rc = thread (NULL);
else {
check ("pthread_attr_init",
pthread_attr_init (&attr));
check ("pthread_attr_setscope",
pthread_attr_setscope (&attr,
PTHREAD_SCOPE_SYSTEM));
check ("pthread_attr_setdetachstate",
pthread_attr_setdetachstate (&attr,
PTHREAD_CREATE_JOINABLE));
check ("pthread_create",
pthread_create (&th, /* thread id */
&attr, /* pthread_attr */
thread, /* start routine */
NULL)); /* start routine arg */
check ("pthread_join",
pthread_join (th, &rc));
}
/* not reached */
return (0);
}
exec(). The attached program demonstrates how the exec() behaves
differently when issued from inside a thread (./p) or directly
from main (./p x). In the former case the shell proceeds when
the exec is issued rather than wait for the completion of the
program.
The problem is that the exec'ed program takes over the pid of
the thread rather than of main(), and the original process
exits, letting my shell proceed rather than wait.
How do I prevent this? I have a need to exec() from inside a
thread and not release a wait()ing parent at that point.
I tried playing with pthread_attr_setscope() but got incorrect
results: non-zero return code and no perror. Just change to
PTHREAD_SCOPE_PROCESS
and see. Anyway, it probably is unrelated.
I looked into process groups and got no solution either.
--
Eyal Lebedinsky (***@eyal.emu.id.au) <http://samba.org/eyal/>
-------------- next part --------------
#include <stdio.h>
#include <sys/types.h> /* pid_t */
#include <unistd.h>
#include <pthread.h>
static pid_t main_pid;
static pid_t main_pgrp;
static pid_t thread_pid;
static pid_t thread_pgrp;
void
check (char *func, int rc)
{
if (rc) {
fprintf (stderr, "%s rc=%d", func, rc);
perror (" ");
exit (1);
}
}
void *
thread (void *parm)
{
thread_pid = getpid ();
thread_pgrp = getpgrp ();
fprintf (stderr,
"thread pid is %ld pgrp is %ld\n",
(long)thread_pid,
(long)thread_pgrp);
execl ("/bin/sh", "sh", "-c", "(sleep 1 ; echo hi from $$)", NULL);
/* not reached */
return (NULL);
}
int
main (int argc, char **argv, char **envp)
{
pthread_attr_t attr;
pthread_t th;
void *rc;
main_pid = getpid ();
main_pgrp = getpgrp ();
fprintf (stderr,
"main pid is %ld pgrp is %ld\n",
(long)main_pid,
(long)main_pgrp);
if (argc > 1)
rc = thread (NULL);
else {
check ("pthread_attr_init",
pthread_attr_init (&attr));
check ("pthread_attr_setscope",
pthread_attr_setscope (&attr,
PTHREAD_SCOPE_SYSTEM));
check ("pthread_attr_setdetachstate",
pthread_attr_setdetachstate (&attr,
PTHREAD_CREATE_JOINABLE));
check ("pthread_create",
pthread_create (&th, /* thread id */
&attr, /* pthread_attr */
thread, /* start routine */
NULL)); /* start routine arg */
check ("pthread_join",
pthread_join (th, &rc));
}
/* not reached */
return (0);
}