pthread에 버그가 있는 듯 합니다.

Hyun의 이미지

이럴 수가...
코드는 ...

#include <pthread.h>
#include <stdio.h>

pthread_t thread;

void *thread_fun( void *arg )
{
        printf( "thread...\n" );

        pthread_cleanup_push( (void(*)(void*))printf, (void*)"cleanup1 called...\n" );
        pthread_cleanup_push( (void(*)(void*))printf, (void*)"cleanup2 called...\n" );
        pthread_cleanup_push( (void(*)(void*))printf, (void*)"cleanup3 called...\n" );

        printf( "cleanup registered.\n" );
        sleep( 10 );
        printf( "sleep done.\n" );

        pthread_cleanup_pop( 1 );
        pthread_cleanup_pop( 1 );
        pthread_cleanup_pop( 1 );

        return NULL;
}

int main( void )
{
        pthread_create( &thread, NULL, thread_fun, NULL );

        sleep( 2 );

        printf( "cancel...\n" );
        pthread_cancel( thread );
        printf( "canceled.\n" );

        pthread_join( thread, NULL );
        printf( "joined...\n" );

        return 0;
}

와 같이 했구요.
Makefile은...
CROSS = powerpc-405-linux-gnu-
CC = $(CROSS)gcc

target = test
objs = main.o

all: $(target)

$(target): $(objs)
        $(CC) $(CFLAGS) -lpthread -o $@ $^

.c.o:
        $(CC) $(CFLAGS) -c -o $@ $<

clean:
        rm -f $(objs) $(target)

install: all
        cp $(target) /home/parkhw00/target/home/parkhw00/tmp/

와 같이 했습니다.
Makefile 첫부분을 주석으로 만들어 pc에서 돌렸을때는...
[parkhw00@daebak pthread_test]$ make clean all
rm -f main.o test
gcc  -c -o main.o main.c
gcc  -lpthread -o test main.o
[parkhw00@daebak pthread_test]$ ./test
thread...
cleanup registered.
cancel...
canceled.
cleanup3 called...
cleanup2 called...
cleanup1 called...
joined...
[parkhw00@daebak pthread_test]$

이렇게 의도한 대로 되는데...
powerpc에서 돌렸을때는
[root@12.34.56.78 parkhw00]# ./tmp/test
thread...
cleanup registered.
cancel...
canceled.
cleanup3 called...
joined...
[root@12.34.56.78 parkhw00]#

처럽 됩니다.
똑같은 소스로 컴파일 했는데...
다른 결과가 나오는군요.
cleanup 함수를 첫번째꺼만 호출하고 바로 쓰래드가 죽어버립니다.
어떻게 하면 좋죠...
pc환경은 페도라코어1이며.
powerpc 환경은 http://kegel.com/crosstool/ 에 있는 크로스 컴파일러를 사용해서 구축했습니다.
타겟보드의 라이브러리 버전은...
-rwxr-xr-x    1 parkhw00 parkhw00  1593370 Feb  4  2004 /lib/libc-2.3.2.so
-rwxr-xr-x    1 parkhw00 parkhw00    90079 Feb  4  2004 /lib/libpthread-0.10.so

이구요...
경험 있으신 분 있나요???
누가 크로스컴파일러로 이런허접질을 할까요...
답글이 달리기를... 라이브러리 버그가 아니기를 기원합니다.
File attachments: 
bugiii의 이미지

printf 를 바로 주지 말고 한번 감싸는 다른 청소 함수를 주면 어떻게 됩니까? 실험 부탁드립니다.

Hyun의 이미지

void print( void *arg )
{
        fprintf( stderr, (const char*)arg );
}

void *thread_fun( void *arg )
{
        print( "thread...\n" );

        pthread_cleanup_push( print, (void*)"cleanup1 called...\n" );
        pthread_cleanup_push( print, (void*)"cleanup2 called...\n" );
        pthread_cleanup_push( print, (void*)"cleanup3 called...\n" );

        print( "cleanup registered.\n" );
        sleep( 10 );
        print( "sleep done.\n" );

        pthread_cleanup_pop( 1 );
        pthread_cleanup_pop( 1 );
        pthread_cleanup_pop( 1 );

        return NULL;
}


욜케 해봤는데...
그래도 똑같네요...
아궁아궁...
시껍이군요...
그래두... 관심 있는분이 있으니 다행이군요... :lol:
bugiii의 이미지

pop( 0 ) 으로 하면 어떻게 됩니까? 또 실험해주셔야겠네요... -_-;

Hyun의 이미지

결과는 똑같습니다.
맨페이지를 보면...

Quote:
pthread_cleanup_pop removes the most recently installed cleanup han-
dler. If the execute argument is not 0, it also executes the handler,
by calling the routine function with arguments arg. If the execute
argument is 0, the handler is only removed but not executed.

라고 되어 있습니다.
pthread_cleanup_pop( 0 )
이라고 하면 program counter가 그 까지 갔을때 등록한 cleanup함수를 호출안하고 그냥 목록에서 지우는것 같습니다.

몬타비스타에서 제공한 powerpc용 pthread library를 사용하면 위와 같은 버그는 없더라구요.
제가 컴파일을 한 것에서만 위와같은 문제가 생기는거 같은데...
컴파일을 잘못한것인지... 패치를 덜 적용한것인지 궁굼하군요...
패치를 어디가면 구할 수 있을지...

Hyun의 이미지

버그 수정했습니다.
powerpc의 c컴파일러가 함수를 호출할대는 스택을 밑을로 자라게 하는데.
한 함수안에서 중괄호를 이용할때는 스택을 위로 자라게 하더군요...

pthread안에서 스택포인터의 위치를 비교하는 루틴이 있어서 제일 마지막에 등록한 하나의 cleanup함수만 등록이 되고 나머지는 등록이 안되던 버그를 수정했습니다.
glibc-linuxthread-2.2.2까지는 버그가 없던데 그 이후버전부터 2.3.2(현재의 최신버전)까지 버그가 있더군요...

x86에서는 문제가 안되는 버그인데... ppc나 다른 프로세서(mips에서도 생긴다는거 같더군요...)에서도 버그가 생긴다고 합니다.

pthread_cleanup_push, pthread_perform_cleanup(pthread_exit에서 호출됨)함수를 수정했습니다.

댓글 첨부 파일: 
첨부파일 크기
Binary Data 0바이트

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.