fopen(3)은 스레드에 안전한가요?

peccavi의 이미지

안녕하세요~

file discriptor가 스레드마다 지역변수로 존재합니다.

그런데, 이 fd들이 하나의 공통된 파일을 fopen한다면,

문제가 생길수 있을까요?
(이 파일은 a+t 의 옵션으로 오픈됩니다, 파일이 삭제되는 일은 없습니다.)

efence를 링크해서 빌드한 바이너리는 항상 fopen에서 SIGSEGV가 떨어지는데

efence를 링크하지 않으면 정상적으로 작동이 되는 현상입니다.

fopen(3) 자체가, 스레드에 안전한 함수가 아니기 때문일까요..?

winner의 이미지

FILE * 는 내부 buffer 를 쓰니까요.

gamdora의 이미지

그럼 lock, write, flush, unlock 순서로 하면 안전할까요?

winner의 이미지

왜 내 기억에 file 관련 표준 함수들이 thread safety 를 지원하지 않는 것으로 남아 있는 것인지...
누가 내 기억을 조작했나?..^_^

하여간 잘못된 정보 죄송합니다.

cinsk의 이미지

SUSv3 (POSIX)를 지원하는 시스템에서는, fopen(3)은 thread-safe한 함수입니다.
SUS(Single Unix Specification)는 http://www.unix.org/single_unix_specification/ 에서 다운로드받을 수 있습니다.

질문이 정확하지 않아서 잘 모르겠지만, file descriptor는 보통 open(2)이 리턴한 것을 가리킬 때 사용되며, fopen(3)이 리턴한 것은 FILE *라고 말씀하시는게 더 정확할 것입니다.

a+t라고 말씀하신 것으로 보아 open(2)이 아닌 fopen(3)을 쓰신 것 같은데, 특별히 fopen(3)이 문제가 있을 것이라고 생각되지는 않습니다. a+t를 미루어 추측컨대, Windows 환경인 것 같군요.

제 시스템에 설치된 efence 도움말을 보면 아래와 같이 나오는데:

Here some Compilation Notes for your Application in Debug Mode
for the Microsoft Visual C++ (v6) Compiler:
 
1) don't use Program Database for "Edit and Continue":
   Project-Options -> C++ -> General -> Debug-Info
2) don't use the "multithreaded-dll" runtime library:
   Project-Options -> C++ -> Code Generation -> Runtime library
3) switch off incremental linking
   Project-Options -> Linker -> General
4) switch off precompiled headers:
   Project-Options -> C++ -> Precompiled Headers
5) add following Linker option "/FORCE:MULTIPLE"
   Project-Options -> Linker -> General

efence를 쓸 때 multithreaded-dll을 쓰지 말라고 나오는군요. 참고 바랍니다.

또, 여러 thread에서 동시에 파일을 기록한다면, flockfile(3), ftrylockfile(3), funlockfile(3)등이 도움이 될 것입니다. 참고하세요.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

cinsk의 이미지

SUSv3에 있는 내용인데 참고하시라고 올려봅니다. (아래에 나와 있는 함수 이외의 다른 POSIX 함수들은 모두 thread-safe하다고 보시면 됩니다.)

All functions defined by this volume of IEEE Std 1003.1-2001 shall be thread-safe, except that the following functions1 need not be thread-safe.
 
 
asctime()
basename()
catgets()
crypt()
ctime()
dbm_clearerr()
dbm_close()
dbm_delete()
dbm_error()
dbm_fetch()
dbm_firstkey()
dbm_nextkey()
dbm_open()
dbm_store()
dirname()
dlerror()
drand48()
ecvt()
encrypt()
endgrent()
endpwent()
endutxent()
fcvt()
ftw()
gcvt()
getc_unlocked()
getchar_unlocked()
getdate()
getenv()
getgrent()
getgrgid()
getgrnam()
gethostbyaddr()
gethostbyname()
gethostent()
getlogin()
getnetbyaddr()
getnetbyname()
getnetent()
getopt()
getprotobyname()
getprotobynumber()
getprotoent()
getpwent()
getpwnam()
getpwuid()
getservbyname()
getservbyport()
getservent()
getutxent()
getutxid()
getutxline()
gmtime()
hcreate()
hdestroy()
hsearch()
inet_ntoa()
l64a()
lgamma()
lgammaf()
lgammal()
localeconv()
localtime()
lrand48()
mrand48()
nftw()
nl_langinfo()
ptsname()
putc_unlocked()
putchar_unlocked()
putenv()
pututxline()
rand()
readdir()
setenv()
setgrent()
setkey()
setpwent()
setutxent()
strerror()
strtok()
ttyname()
unsetenv()
wcstombs()
wctomb()
 
 
The ctermid() and tmpnam() functions need not be thread-safe if passed a NULL argument. The wcrtomb() and wcsrtombs() functions need not be thread-safe if passed a NULL ps argument.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/
peccavi의 이미지

file pointer가 맞는 말이겠군요..

흠.. 코드를 몇번이나 다시 봤습니다만, fopen전후에 문제를 일으킬만한

내용이 없는데, 왜 fopen에서 SIGSEGV가 나는지 알수가 없네요.
(프로그램을 실행해서 스레드들이 fopen에 진입하자마자 SIGSEGV가 나오진 않습니다.
어느정도 시간이 지난뒤 랜덤하게..)

사실, mutex구조를 몇개 바꾸고 file잠금을 추가하면 문제없이 해결되겠지만
그것보다, fopen이 문제를 일으켰다는걸 증명하는게 더 중요하게 되버렸네요..
조금 더 테스트를 해봐야 겠습니다.

답변주신 두분 많은 도움이 됐습니다. 정말 감사드립니다~

----
jai guru deva om...

----
jai guru deva om...

댓글 달기

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