This is a piece of code that the client receives a service-side answer in a short socket connection:
/************ Receive Response message ****************/
Alarm (20);
Iret=read (yktsocketid,recvbuf,2048);
Alarm (0);
if (iret<=0)
{
memset (logbuf,0,sizeof (LOGBUF));
sprintf (Logbuf, "iret=[%d],file=[%s],line=[%d]\n", iret,__file__,__line__);
Lwritelog (Logfile,logbuf,strlen (LOGBUF), 6);
return-1;
}
The main idea of the code is to set a 20-second time-out. If the server answers time-outs, captures the sigalarm signal, IRET<=0 returns an error message.
So now the problem is, the default processing of the Sigalarm signal is to terminate the process: This is different from what we expected, and was meant to be sigalarm after capturing the signal in the read call and returning an error. Then the processing of the sigalarm signal needs to be rewritten to allow the process to be terminated.
struct Sigaction Act;
Act.sa_handler = Alarm_catch;
Sigemptyset (&act.sa_mask);
Act.sa_flags |= Sa_interrupt;
Sigaction (SIGALRM, &act,null);
Alarm (20);
Iret=read (yktsocketid,recvbuf,2048);
Alarm (0);
if (iret<=0)
{
memset (logbuf,0,sizeof (LOGBUF));
sprintf (Logbuf, "iret=[%d],file=[%s],line=[%d]\n", iret,__file__,__line__);
Lwritelog (Logfile,logbuf,strlen (LOGBUF), 6);
return-1;
}
This rewrite of the sigalarm signal processing can be a perfect solution to the problem of the termination process, then the code is perfect now. It's not that simple, hehe.
There is a race condition between the first a l a r m call and the R e a D call. If the kernel is in between these two function calls so that the process cannot occupy the processor and its time is longer than the alarm
, then r e a D may block forever. Timeout will expire ....
This problem can be introduced setjmp to solve
struct Sigaction Act;
static jmp_buf ENV_ARLM;
Act.sa_handler = Alarm_catch;
Sigemptyset (&act.sa_mask);
Act.sa_flags |= sa_interrupt;
sigaction (SIGALRM, &act,null);
if (setjmp (ENV_ARLM) ==0)
{ alarm (20);
iret=read (yktsocketid,recvbuf,2048);
Alarm (0);
if (iret<=0)
{
memset (logbuf,0,sizeof (LOGBUF));
sprintf (logbuf, "iret=[%d],file=[%s],line=[%d]\n", iret,__file__,__line__);
Lwritelog (Logfile,logbuf,strlen (LOGBUF), 6);
return-1;
&NBSP;}
}
Return (alarm (0));
static void Alarm_catch ()
{
longjmp (ENV_ARLM, 1);
}
This allows the system to jump directly to return even if the timeout process is completed before read. Does not jump to read slow IO this piece
In addition a small problem is added:
In my program, I defined a
Long BankID;
There is no initialization, the bankid=5555 is called, and garbled characters are still present after the value is assigned. The automatic variable is still initialized, today
It's an education.