- 论坛徽章:
- 1
|
最近看《unix网络编程》看到第五章,想试验一下那个主进程wait子进程结束信号SIGCHLD这个信号,用书上的例子,在测试过程中出现一个问题,不知道怎么解析,想了一天也没想通。流程很简单:
1、服务器运行(等待客户端连接)。
2、客户端运行,输入一行,按回车(服务器里面返回客户端输入的内容)。
3、客户端ctrl + D 结束。
4、服务端处理完SIGCHLD信号后段错误。(正常是处理完SIGCHLD信号,就继续阻塞ACCEPT)。
一下是代码。
客户端(这个没有问题,不看也可以),问题在服务端的代码里面,有注释。- #include "unp.h"
- void str_cli(FILE *fp, int fd)
- {
- char send[MAXLINE], recv[MAXLINE];
- while(fgets(send, MAXLINE, fp) != NULL)
- {
- int n = writen(fd, send, strlen(send));
- //if (readn(fd, recv, MAXLINE) == 0)
- if (readline(fd, recv, MAXLINE) == 0)
- {
- printf("readn return 0,then close");
- close(fd);
- exit(0);
- }
- fputs(recv, stdout);
- }
- }
- int main(int argc, char *argv[])
- {
- int fd = socket(AF_INET, SOCK_STREAM, 0);
-
- struct sockaddr_in ser;
-
- if (argc < 2)
- {
- printf("usage app ip\n");
- return 1;
- }
- bzero(&ser, sizeof(sockaddr_in));
- ser.sin_family = AF_INET;
- ser.sin_port = htons(5005);
- inet_pton(AF_INET, argv[1], &ser.sin_addr);
-
- socklen_t len = sizeof(ser);
- if (connect(fd, (struct sockaddr *)&ser, len) != 0)
- {
- printf("connect error:%s.\n", strerror(errno));
- return 1;
- }
- else printf("connect success.\n");
- str_cli(stdin, fd);
- exit(1);
- return 1;
- }
复制代码 服务端:(这个是有问题的)- #include "unp.h"
- void sig_handle(int sig)
- {
- pid_t pid;
- int status;
- pid = wait(&status);
- printf("child %d terminated\n", pid);
- return;
- }
- void str_echo(int fd)
- {
- ssize_t n;
- char buf[MAXLINE];
- memset(buf, '\0', sizeof(buf));
- again:
- while((n = read(fd, buf, MAXLINE)) > 0) writen(fd, buf, n);
- if (n < 0 && errno == EINTR)
- {
- printf("got again\n");
- goto again;
- }
- else if (n < 0)
- {
- printf("read error...........\n");
- }
- }
- int main(int argc, char *argv[])
- {
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- struct sockaddr_in ser, cli;
- struct sigaction act, oact;
- act.sa_handler = sig_handle;
- sigemptyset(&act.sa_mask);
- //act.sa_flags = 0;
- if (sigaction(SIGCHLD, &act, &oact) < 0)
- {
- printf("sigaction error\n");
- }
- else
- {
- printf("sigact succ.\n");
- }
- bzero(&ser, sizeof(sockaddr_in));
- bzero(&cli, sizeof(sockaddr_in));
- ser.sin_family = AF_INET;
- ser.sin_port = htons(5005);
- ser.sin_addr.s_addr = htonl(INADDR_ANY);
- socklen_t len = sizeof(sockaddr_in);
- if (bind(fd, (struct sockaddr *)&ser, len) != 0)
- {
- printf("bind error:%s.\n", strerror(errno));
- return 1;
- }
- else printf("bind success.\n");
- listen(fd, 5);
- while(true)
- {
- int cfd = accept(fd, (struct sockaddr *)&cli, &len);
- if (cfd < 0 && errno == EINTR)
- {
- printf("accept intrrupt by intr,continue.\n");
- continue;
- }
- else
- {
- char c = 'A';//问题在这里,如果没有这个无关的定义就会断错误。
- }
- pid_t pid = 0;
- if ((pid = fork()) == 0)
- {
- close(fd);
- str_echo(cfd);
- printf("return from str_echo.\n");
- exit(0);
- }
- else
- {
- printf("fork pid = %d\n", pid);
- }
- close(cfd);
- printf("farther close cfd.\n");
- }
-
- return 1;
- }
复制代码 问题是:
在服务端accept返回来的下面那段代码:- if (cfd < 0 && errno == EINTR)
- {
- printf("accept intrrupt by intr,continue.\n");
- continue;
- }
- else
- {
- char c = 'A';
- }
复制代码 如果没有加char c = 'A';这一行,那么在处理完SIGCHLD信号后就段错误了。如果加了这一行就可以顺利运行。事实上着一行随便写个 int a = 1000;也不会段错误。这个怎么解析?不科学啊!这行代码应该不会有执行的机会的(因为正常的时候都是执行cfd < 0 && errno == EINTR 那个条件里面的代码)。但是没有这行代码,就立即段错误。求解! |
|