2012-03-06 1 views
1

프로세스에 두 개의 스레드가 있습니다. 이 두 스레드는 세마포어로 동기화하려고 시도하는 공유 메모리에 대한 경쟁을 가지고 있습니다. 하지만 한 스레드가 다른 스레드와 나란히 semop 함수를 호출 할 때 errno 4에서 임의로 오류가 발생했습니다. 나는 약간 파고를했고 시스템 콜에 의해 호출이 중단 된 것처럼 보였다.semop()는 errno와 함께 실패했습니다. 4. 프로세스 내에서 스레드 semop()가 스레드 레이스를 지원합니까?

EINTR이 시스템 호출에서 차단되었지만 프로세스에서 신호를 포착했습니다. 신호 (7) 참조. errno 4 이거 야?

있습니다 라인 (583) 및

(601)는 시스템 호출을 중단? 함수 semop() 자체? 어떤 식 으로든이 시스템 호출을 무시하고이 함수를 중단 시키거나 복구/다시 시작 하시겠습니까?

semop은 멀티 스레드 환경에서 사용할 수 있습니까?

[Switching to Thread -1208269120 (LWP 4501)] 
GetMyQue2Wait (MyModule=RM, wait_shm_ptr=0xbf8a5cf4) at tdm_ipc.c:247 
247            TDM_SEM_P(MyModule); 
(gdb) s 
tdm_sem_p (mid=RM) at tdm_ipc.c:579 
579    sem_b.sem_num = 0; 
(gdb) s 
580    sem_b.sem_op = -1; 
(gdb) s 
581    sem_b.sem_flg = SEM_UNDO; 
(gdb) s 
583    if (semop(TDM_M[mid].semid, &sem_b, 1) == -1) 
(gdb) s 
[Switching to Thread -1208480880 (LWP 4506)] 

GetMyQue2Send (MyModule=RM, send_shm_ptr=0xb7f7ff54) at tdm_ipc.c:180 
180    DMINT   TryTimes = SEND_TIMES; 
(gdb) s 
353    TDM_SEM_V(DstModule); 
(gdb) s 
tdm_sem_v (mid=RM) at tdm_ipc.c:597 
597    sem_b.sem_num = 0; 
(gdb) s 
598    sem_b.sem_op = 1; 
(gdb) s 
599    sem_b.sem_flg = SEM_UNDO; 
(gdb) s 
601    if (semop(TDM_M[mid].semid, &sem_b, 1) == -1) 
(gdb) s 
606    return SUCC; 
(gdb) s 
607  } 


(gdb) s 
RM:4501: V operation on Semaphore . 
SEND_MSG (SrcModule=51, DstModule=RM, msg_ptr=0xb7f7ff94, MsgLength=28) at tdm_ipc.c:368 
368    printf("%s:%d: SEND_MSG: succeeded.\n", 
(gdb) s 
RM:4501: SEND_MSG: succeeded. 
[Switching to Thread -1208269120 (LWP 4501)] 
tdm_sem_p (mid=RM) at tdm_ipc.c:585 
585      printf("thread %u: errno = %d\n", (unsigned int)pthread_self(),errno); 
(gdb) s 
thread 3086698176: errno = 4 
[Switching to Thread -1208480880 (LWP 4506)] 



main thread: 

     ... 
     while(1) 
      { 
       if ((RetVal = WAIT_MSG(p1, &Msg)) !=SUCC) 
       { 
        switch (RetVal) 
        { 
        ... 
         } 
        } 
      } 
    ------------------------------------ 
     thread1: 
     ... 
     send(src, dst, &msg, lenght); 

     /* both SEND_MSG() and WAIT_MSG() have an operation P and V on semid by calling the following */ 

     DMINT tdm_sem_p(key_t semid) 
     { 
      struct sembuf sem_b; 

      sem_b.sem_num = 0; 
      sem_b.sem_op = -1; 
      sem_b.sem_flg = SEM_UNDO; 

      if (semop(semid, &sem_b, 1) == -1) 
      { 
       printf("thread %u: errno = %d\n", (unsigned int)pthread_self(),errno); 

       return S_PFAIL; 
      } 

      return SUCC; 
     } 

     DMINT tdm_sem_v(key_t semid) 
     { 
      struct sembuf sem_b; 

      sem_b.sem_num = 0; 
      sem_b.sem_op = 1; 
      sem_b.sem_flg = SEM_UNDO; 

      if (semop(semid, &sem_b, 1) == -1) 
      { 
       return S_VFAIL; 
      } 

      return SUCC; 
     } 

     /* semid is init by the following */ 
     DMINT tdm_set_sem(key_t semid) 
     { 
      union semun sem_union; 
      sem_union.val = 1; 

      if (semctl(semid, 0, SETVAL, sem_union) == -1) 
      { 
       return FAILURE; 
      } 
      return SUCC; 
     } 

이 문제에는 나쁜 문제 설명이있는 다른 링크가 있습니다. P semaphore failed

감사합니다.

+0

코드 스 니펫을 공유하면 도움이됩니다. – noMAD

+0

나는 그것을 추가했다. 감사. –

답변

6

Errno 4는 실제로 EINTR입니다. 이 오류가 발생하면 실행중인 시스템 호출 (이 경우 semop)이 신호에 의해 중단되었음을 의미합니다.

귀하는이 경우 시스템 호출을 다시 시작해야합니다. 제한된 시스템 호출 집합 만 자동으로 다시 시작되고 신호 처리기가 SA_RESTART 플래그를 사용하여 설정된 경우에만 수행됩니다. 자세한 내용은 "신호 처리기에 의한 시스템 호출 및 라이브러리 함수 중단"절에 대한 내용은 signal(7)을 참조하십시오. 신호 처리기의 처리 상태에 관계없이 이 이 아닌이 다시 시작된 시스템 호출 목록에 있음을 알 수 있습니다.

통화를 다시 시작하는 방법은 귀하에게 달려 있습니다. 당신이 그 신호에 대한 핸들러가 없다면 당신은 주어진 시스템 호출을 중단 어떤 신호 모르는

int rc; 

while ((rc = semop(...)) == -1) { 
    if (errno != EINTR) { 
    break; 
    } else { 
    // decide whether to restart the call after interruption 
    // or not 
    } 
} 
// here, if rc == 0, semop worked, otherwise an error different from 
// EINTR happened (or you decided not to restart) 

: 방법 중 하나는 그런 짓을하는 것입니다. gdb에는 options for signal handling이 있습니다. 따라서 시도해 볼 수 있습니다. 어쩌면 시작하려면 handle all print을 시도하십시오.

0

문제의 프로세스를 strace ... semop이 실패 할 때 인터럽트되는 신호가 표시되어야합니다.

관련 문제