clone + glib thread pool



Hi,

We need following scenario in our code:
A process uses clone system call to create a thread and that thread chroots
into a specific directory and creates glib threadpool and exits. We need to
use clone system call to have chrooted environment only for the glib
threadpool while main process continues with the default root.

Question: A thread which creates glib threadpool exits using syscall, is
this behaviour allowed? Is there any assumption/need in glib threadpool that
parent thread needs to available till glib threadpool running?

I am attaching a sample code, which demonstrates above scneario

In the sample code, if I do exit/_exit in 'threadFunction' , it results in
terminating glib threadpool also. So syscall(__NR_exit) is used to ensure that
even after the termination of parent thread, glib threadpools continue to be
executing

#include <malloc.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>	/* For SYS_xxx definitions */
#include <sys/stat.h>
#include <stdlib.h>
#include <glib-2.0/glib.h>
#include <fcntl.h>

GThreadPool *pool;
#define STACK_SIZE 1024*64

int pass_fd = -1;

void thread_routine(gpointer data, gpointer user_data)
{
    struct stat buf;

    if (stat("/passwd", &buf)) {
	perror("stat");
	return;
    }
    pass_fd = open("/passwd", O_RDONLY);
    if (pass_fd < 0) {
	perror("open");
    }
}


// The child thread will execute this function
int threadFunction(void *argument)
{
    GError *err;
    if (chroot("/etc") < 0) {
	perror("chroot");
    }

    if (!g_thread_supported()) {
	g_thread_init(NULL);
    }
    pool = g_thread_pool_new(thread_routine, &pass_fd, 4, TRUE, &err);
    if (pool == NULL) {
	printf("g_thread_pool_new failed: %s\n", err->message);
	exit(1);
    }
    syscall(__NR_exit, 0);
}

int main()
{
    void *stack;
    pid_t pid;
    int err, i;
    struct stat buf;
    char ch;

    stack = malloc(STACK_SIZE);
    if (stack == 0) {
	perror("malloc");
	exit(1);
    }

    pid = clone(&threadFunction, (char *) stack + STACK_SIZE,
		SIGCHLD | CLONE_FILES | CLONE_SIGHAND |
		CLONE_VM | CLONE_THREAD, 0);
    if (pid == -1) {
	perror("clone");
	exit(2);
    }

    free(stack);
    sleep(1);
    g_thread_pool_push(pool, &pass_fd, NULL);
    sleep(1);
    if (pass_fd != -1) {
	err = fstat(pass_fd, &buf);
	printf("/etc/passwd size %d\n", buf.st_size);
    } else {
	printf("pass_fd is -1\n");
    }
    return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]