freebsd 에서 fork 후 thread 실행시에 'mutex is on list' 오류 발생에 대해서.

sunbee의 이미지

안녕하세요..

아래 소스를 리눅스에서 실행시켜, 자식 프로세스를 kill 하면 부모 프로세스가 signal을 catch 하여 자식 프로세스를 다시 기동시키는데
문제가 없습니다.

하지만, 똑같은 소스를 freebsd (5.4, 6.1) 에서 실행시켜 자식 프로세스를 kill 했을때,
자식 프로세스에서 thread 를 기동하는 순간

소스코드 SpawnProcess() 의
thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
thrad create 하는 부분에서

Fatal error 'mutex is on list' at line 540 in file /usr/src/lib/libpthread/thread/thr_mutex.c (errno = 0)

와 같은 에러가 발생하네요..

혹시 왜 그런지 아는 분 계시면 가르쳐 주시겠습니까?

이것저것 테스트 하느라 소스가 지저분 한건 이해해주세요~^^

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
 
void thr_status()
{
	pthread_attr_t attr;
    int policy;
    printf("Thread Create\n");
    pthread_attr_getdetachstate(&attr, &policy);
    if (policy == PTHREAD_CREATE_JOINABLE)
    {
        printf ("Join able\n");
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    }
    else if (policy == PTHREAD_CREATE_DETACHED)
    {
        printf ("Detache\n");
    }
}
 
void *t_function(void *data)
{
    int id;
    int i = 0;
    id = *((int *)data);
 
	thr_status();
//pthread_detach(pthread_self());
sleep(1);
	thr_status();
 
    while(1)
    {
        printf("%d : %d\n", id, i);
        i++;
        sleep(1);
    }
}
 
int SpawnProcess()
{
    pthread_t p_thread = 0;
    int thr_id = 0;
    int a = 1;
    int status;
 
    int pid=0;
 
/*
	int stacksize = 10;
    pthread_attr_t  attr;
    pthread_attr_init(&attr);
	if (!pthread_attr_setstacksize(&attr, stacksize*1024)) {
	    printf("set stacksize = %dKB\n", stacksize);
    }
    if (!pthread_attr_getstacksize(&attr, &stacksize)) {
        printf("stack size = %d\n", stacksize);
    }
    printf("PTHREAD_THREAD_MAX in limits.h is %u\n", PTHREAD_THREADS_MAX);
*/
 
fprintf(stderr, "before fork \n");
    pid = fork();
    switch(pid)
    {
    case 0:
	// child create thread
fprintf(stderr, "child forked p_thread = (%d), (%p)\n", p_thread, &p_thread);
        // 프로세스 다시 실행시에 여기서 죽어요!!
        thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
        //thr_id = pthread_create(&p_thread, &attr, t_function, (void *)&a);
        pthread_join(p_thread, (void **)&status);
        exit(0);
 
    case -1:
        return 0;
 
    default:
	break;
    }
 
    return 1;
}
 
int WatchChildProcess()
{
    int status;
    pid_t wait_pid;
 
    wait_pid = waitpid(-1, &status, WUNTRACED|WNOHANG);
    if(wait_pid <= 0)
    {
        //sleep(5);
        return 1;
    }
 
    if(wait_pid > 0) /* process killed */
    {
        if (WIFEXITED(status))
        {
            printf("1.Catch the signal. pid=(%d) status=(%d,%d)\n", wait_pid, WIFEXITED(status), WEXITSTATUS(status));
        }
        else if (WIFSIGNALED(status))
        {
            if(WIFEXITED(status) == SIGXFSZ) // file size excess.
            {
 
            }
 
            printf("2.Catch the signal. pid=(%d) status=(%d,%d)\n", wait_pid, status, WIFSIGNALED(status));
        }
 
        /** 
        *   restart child process
        */
        if(!SpawnProcess())
        {
            return 0;
        }
printf("Child Process Spawn Success \n");
    }
 
    return 1;
}
 
int main()
{
    pthread_t p_thread[2];
    int thr_id;
    int status;
    int b = 2;
 
	SpawnProcess();
 
	// parent thread create
    thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
 
     // 프로세스 감시
	while(1)
	{
		WatchChildProcess();
		sleep(1);
	}
    pthread_join(p_thread[1], (void **)&status);
 
    return 0;
}

nineye의 이미지


multi-threaded 환경에서 fork까지... 테스트 프로그램이긴 하지만 정말 복잡하네요...
multi-threaded 환경에서 fork를 호출하는 것은 동기화 관점에서 문제가 발생할 가능성이 큽니다.
왜냐면 부모 프로세스에서의 동기화의 상태가 자식 프로세스에서도 동일하다고 할 수는 없으니까요...
즉, 부모 프로세스에서 fork를 호출하는 thread 이외의, 특정 thread가 mutex를 locking한 상태에서
fork가 호출되면, 자식 프로세스는 존재하지 않는 thread로 인해 mutex가 locking된 상태로
있게 됩니다. deadlock이죠.
thread와 fork가 혼용된 코드를 짜본적이 없어서 정확히 뭐라고 답은 못드리지만, 위와 같이
동기화와 관련된 문제가 아닐까 생각되네요.

pthread 라이브러리에서는 위와 같은 현상을 방지하기 위해, fork호울 시 사용하는 pthread_atfork()
라는 함수를 제공합니다. 이 함수를 사용해서 한 번 테스트 해보시는 것도 괜찮을 듯 합니다.

_________________________________________________________

nineye's blog

_________________________________________________________

nineye's blog

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.