我在一个过程中有两个线程.这两个线程竞争共享内存,尝试通过信号量进行同步.但是当一个线程紧挨着另一个线程调用semop函数时,我随机地使用errno 4失败了.我做了一点挖掘,发现似乎呼叫被系统调用打断了.
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;
}
Run Code Online (Sandbox Code Playgroud)
这个问题有另一个链接可能有一个不好的问题描述. P信号量失败了
谢谢.
Errno 4确实如此EINTR.当您收到该错误时,表示您正在运行的系统调用(semop在这种情况下)被信号中断.
在这种情况下,您负责重新启动系统调用.只有一组有限的系统调用会自动重启,然后才会使用该SA_RESTART标志设置信号处理程序.有关signal(7)详细信息,请参阅"信号处理程序中断系统调用和库函数"部分.无论信号处理程序的处置方式如何,您都会注意到semop系统调用列表中永远不会重新启动.
你如何重新开始通话取决于你.其中一种方法是做一些事情:
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)
Run Code Online (Sandbox Code Playgroud)
除非您有该信号的处理程序,否则您不知道哪个信号中断了给定的系统调用.gdb确实有信号处理选项,所以你可以尝试找出它.尝试handle all print从也许开始.