리눅스 pthread 사용 시 suspend() 함수 만들기

uviczz의 이미지

안녕하십니까?

제가 궁금한 점은 제목과 같이..
리눅스에서 pthread를 이용한 프로그래밍 중 suspend 함수를 만드는 것입니다.

posix 계열에서 pthread_suspend(pthread_t pid); 와 같은 함수가 지원되지 않는다고 하는데,
검색을 통해 알아보니
pthread_mutex_lock(), pthread_mutex_unlock(), pthread_cond_wait(), phtread_cond_signal()
등을 통해서 비슷한 동작이 구현 가능하다고 합니다.

그런데 제가 볼 때 위의 함수들로는 특정 쓰레드 ID를 suspend, resume 시키는게 가능할 지 의문스럽습니다.

관련된 내용에 답변 주시면 감사드리겠습니다.

cinsk의 이미지

해당 thread가 원하지 않는데, 다른 thread에서 그 thread를 suspend/resume하는 방법은 없습니다. POSIX thread에서 thread suspend/resume은, 해당 thread가 자발적으로 pthread_cond_wait()등을 부르고, 다른 thread에서 pthread_cond_signal()등을 불러서 깨우는 방식을 씁니다.

suspend/resume을 (잘못된 방법으로) 남용하면 안좋다고 하는데, 참고하기 바랍니다. 구조를 자발적인 waiting on condition variable 형태로 바꾸는 것이 좋을 것 같습니다.

아니다. 난 무조건 suspend/resume이 필요하다라고 하신다면, 찾으시는 함수는 conditional variable에 관한 것이 아니라, pthread_kill, sigwait를 찾아보기 바랍니다. 하지만 별로 추천하고 싶지 않네요.

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

uviczz의 이미지

저도 다른 thread가 강제로 suspend, resume 시키는 방법 중
pthread_kill을 사용하는 방법을 사용해 보려고 했는데,,

signo에 SIGSTOP, SIGTSTP 등을 이용해서 멈추게 하려고 하니,,
Ctrl+Z와 같이 동작하여, 동작중인 프로그램이 쉘로 빠져나와버리는 현상이 일어났습니다.

ps -ef로 확인하니 프로세스는 그냥 살아있던데,
Ctrl+Z는 제가 원하는 동작이 아니기도 하고,,

sigwait는 확인해봐야 하겠습니다만,,

그리고,, 제 상황은 꼭 다른 쓰레드를 suspend/resume 시키고자 하는데,,
말씀하신 마지막 방법들은 왜 추천하시지 않는지도 같이 궁금합니다.

다시 한번 감사드립니다.

cinsk의 이미지

SIGSTOP은 catch가 불가능합니다. 궂이 이 방식을 쓰겠다면 SIGUSR1, SIGUSR2 등을 쓰는 게 좋습니다.

또, 시그널을 받는 시점에서 thread가 system call 또는 library function 등을 실행하고 있었다면, signal handler가 호출된 다음, 어떤 식으로 동작하는지 모두 생각해봐야 합니다. 시그널을 받고 다시 시작하는 함수가 있는 반면 EINTR 에러를 발생시키는 함수도 있으므로, 해당 thread가 시그널을 받을 수 있는 상태에 있는 모든 코드를 검사해야 합니다. 따라서 안전하게 thread에 signal을 전달하려면, 해당 thread가 wait 상태에 있는 것이 좋습니다. 이 것을 위해 sigwait()를 쓰는데, 해당 thread가 시그널을 받을 상태가 정해져 있다면, conditional variable을 쓰도록 쉽게 바꿀 수 있습니다. 자세한 것은 man 7 signal

pthread에서 thread를 동기화를 위해 이미, conditional variable을 제공하고 있으므로, 이 방식을 쓰는 것이 안전하고 바람직합니다. 강제로 suspend 시키면 위와 같은 이유에서 모든 코드가 안전하고 제대로 에러 처리 등을 하는 지 살펴봐야 하는데, 쉬운일이 아닙니다. 또 일반적으로 multi-threaded application에서 UNIX 시그널을 함께 처리하는 것은 꽤 힘든 일입니다. pthread_kill()을 쓰면 그나마 시그널을 받을 thread를 지정하기 때문에 괜찮지만, 그렇지 않은 경우, 어떤 thread가 signal을 받을 지 모르므로, pthread_sigmask()등을 잘 써야 합니다.

참고로, 디버깅하기 가장 힘든 프로그램 중 하나가: fork()를 사용하면서 (즉 multi-process), thread가 하나 이상이고, UNIX signal을 쓰는 모델에서 발생하는 버그입니다. 질문하신 내용을 보면 multi-process는 아니지만, 나머지 조건을 다 만족하므로, 저라면 디버깅 부탁 거절합니다. ^^;

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

uviczz의 이미지

위에서 말씀 드린 것 처럼 쓰레드 내부에서 시그널을 받을 상태로 들어가 있지 않고,,
쓰레드 외부에서 제어하려고 하다보니,, 어려운 점이 많은 것 같습니다...

조금 더 고민해보고 글 올리겠습니다.

재차 우문 현답 주셔서 감사드립니다!

sauron의 이미지

-- 그리고,, 제 상황은 꼭 다른 쓰레드를 suspend/resume 시키고자 하는데,,
-- 말씀하신 마지막 방법들은 왜 추천하시지 않는지도 같이 궁금합니다.

도데체 그런 상황이란게 어떤 상황일까요.
suspend/resume 을 써야 할 상황이 있다라는 게 뭔가 설계가 잘못되어 있다는 것을 뜻합니다.
어떤 상황인지 구체적으로 알려주셧으면 좋겠네요.

uviczz의 이미지

Windows 프로그래밍을 하다보면,,
Thread 관련 함수 중 CWinThread::SuspendThread와 같은 함수가 있습니다.
단순히 Thread ID만 알면 suspend 시킬 수가 있죠..

설계가 잘못 되있다기 보다,,
그와 같은 API를 구현하고자 여쭤본 것입니다.

cinsk의 이미지

suspend/resume을 쓴다는 자체가 문제가 아니라, 잘못 쓰일 가능성이 높다는 의견이었습니다.

A thread가 B thread를 suspend시킬 경우, B가 현재 무슨 일을 하고 있는지 A가 잘 모른다고 가정해 봅시다. 만약 B가 mutex를 lock하고 있었는데 suspend된다면, 이 mutex를 풀 방법이 애매해집니다. 꼭 mutex가 아니더라도 모든 resource가 이런 문제가 발생할 수 있습니다.

예: 10개의 thread가 있고, 각각 모두 같은 파일에 대해 메시지를 기록하고 있다고 가정. 각 thread는 동기화를 위해, flockfile/funlockfile을 써서 파일을 잠그고 해제하는 일을 반복. 이 때 A thread가 B thread를 suspend시킴. B는 그때, flockfile()을 부르고, write(2)를 써서 메시지의 일부만 파일에 기록한 상태. 이 경우, 파일에 대한 권한는 B thread에 있는데, suspend되면, 나머지 thread는 모두 메시지 기록 불가 상태에 빠짐.

suspend/resume을 UNIX signal을 써서 직접 구현했을 경우, 1) pthread의 거의 모든 함수는 signal handler에서 안전하다는 보장이 없습니다. signal handler에 쓰일 수 있는 안전한 함수 목록은 man 7 signal 참고. 2) 앞에서도 설명했지만, 한 thread가 slow system call을 수행 중일 경우, signal을 받았을 때에 대한 모든 대비가 되어 있어야 합니다.

다시 한번 말하지만, A thread가 B thread를 suspend시킬 경우, B가 무슨 상태인지 A가 잘 알고 있으며, B도 suspend될 상태를 예측할 수 있다면, conditional variable을 쓰도록 쉽게 바꿀 수 있습니다.

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

uviczz의 이미지

문제를 주말동안 잠시 잊고 있느라,,
답글을 늦게 확인 했습니다.

말씀하신 부분을 보면 어떤 동작을 하고 있는지 모르는 Thread를 강제로 suspend 시키는 것은
굉장히 위험한 일인데,, 기타 여러 OS에서는 그러한 함수를 왜 지원하는지 모르겠습니다..

그리고 답변 매우 감사드립니다.

댓글 달기

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