我想在我的linux项目中异步地使用PostgreSQL (9.1)。为此,我必须使用epoll_wait (因为应用程序的其他部分)。最终目标将是在边缘触发模式下使用epoll。但是,即使在非边缘触发模式下,我也无法使连接过程工作。我也不知道为什么。然而,当用户名和密码是正确的,它是有效的。但是,当密码错误时,它也必须工作。在这种情况下,我会犯一些我不明白的错误。-/这里是我使用的代码(连接已经用PQconnectStart()和PQconnectdb()很好地工作的参数列表初始化了):
void ConnectDB(PGconn * connection)
{
int pq_fd = PQsocket(connection);
int epoll_fd = epoll_create1(0);
struct epoll_event event;
struct epoll_event *eventList = (epoll_event *)calloc(64, sizeof(epoll_event));
event.data.fd = pq_fd;
event.events = EPOLLOUT | EPOLLERR;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pq_fd, &event);
while (true) {
PostgresPollingStatusType pt = PQconnectPoll(connection);
switch (pt)
{
case PGRES_POLLING_OK:
printf("*** connection established!\n");
return;
case PGRES_POLLING_FAILED:
printf("*** connection failed: %s\n", PQerrorMessage(connection));
return;
case PGRES_POLLING_ACTIVE:
printf(" --- poll result: PGRES_POLLING_ACTIVE\n");
break;
case PGRES_POLLING_READING:
printf(" --- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN\n");
event.events = EPOLLIN | EPOLLERR;
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
break;
case PGRES_POLLING_WRITING:
printf(" --- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT\n");
event.events = EPOLLOUT | EPOLLERR;
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
break;
}
int n = epoll_wait(epoll_fd, eventList, 64, -1);
if (n == -1) {
printf("epoll_wait() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
}
}这是我得到的输出:
--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_READING - Modifiing epoll to EPOLLIN
--- poll result: PGRES_POLLING_WRITING - Modifiing epoll to EPOLLOUT
epoll_ctl() error: 2: No such file or directory有什么主意吗?
发布于 2016-02-03 19:15:36
postgresql客户端库首先尝试ssl连接,如果失败,它将在不使用ssl的情况下重试。无论连接失败的原因是什么,它都是这样做的,而且完全没有通知调用方。因此,即使错误是错误的密码,客户端库也将关闭filedescriptor并重新打开套接字连接以获取明文。
如果文件关闭,它将自动从epoll-集中删除(这将导致您的“没有这样的文件或目录”错误消息)。因此,您必须手动重新添加:
if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, PQsocket(connection), &event) == -1) {
if (errno == ENOENT) {
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, PQsocket(connection), &event);
} else {
printf("epoll_ctl() error: %u: %s\n", errno, strerror(errno));
exit(1);
}
}另一个选项是永久启用或禁用ssl,为此将sslmode=require或sslmode=disable添加到连接字符串中。但是,如果您计划使用PGreset() (或者遇到任何其他情况,其中套接字被关闭并对调用方透明地重新打开),那么您就会遇到同样的问题。
诚然,postgresql库的这种行为不是很epoll()-friendly。在过去,当使用select()或poll()时,这不是一个问题,因为内核中没有像现在的epoll()那样的状态。
https://stackoverflow.com/questions/35184780
复制相似问题