[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
How use ssh_select after fail in ssh_bind_accept?
[Thread Prev] | [Thread Next]
- Subject: How use ssh_select after fail in ssh_bind_accept?
- From: samail@xxxxx
- Reply-to: libssh@xxxxxxxxxx
- Date: Tue, 17 Mar 2015 12:10:51 +0300
- To: libssh@xxxxxxxxxx
Hello, I have question about using of ssh_select. It's required to wait events on several descriptors (ssh and not ssh). The system select or ssh_select can be used for this purpose. But I have problem with error cases after ssh_bind_accept(). Common algorithm is: while ( ssh_select( descrs) == SSH_OK) { if (ssh_listen_descr is set) { ssh_bind_accept() // create session etc } else if ( other descr) { .... } } When ssh_bind_accept() returns error (for example: 'too many open files' or 'Can't open file'), then ssh_select() will return read event on listening ssh descriptor always. Event the client has stopped already. How I can process an error of ssh_bind_accept() to avoid endless events in ssh_select() ? Code example in attach. To reproduce problem try to connect to port=2222. Note: example will create many files 'delmeXXX' in current dir. Example of output: Max open file count was reached: can't open file delme252 (253 files opened). errno=24, strerror: Too many open files Wait for ssh_select ssh_select result: 0 ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files Can't accept connection Wait for ssh_select ssh_select result: 0 ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files Can't accept connection Wait for ssh_select ssh_select result: 0 ssh_bind_accept failed: Error opening ./ssh_host_dsa_key: Too many open files Can't accept connection Wait for ssh_select ssh_select result: 0 ... So, select have endless read event on litening FD. -- Regards, Andrey
/* CC ./server.cc -I/home/shamanin/tmp/libssh/include -I/home/shamanin/tmp/libssh/openssl/inc /home/shamanin/tmp/libssh/libssh_static.a /home/shamanin/tmp/libssh/openssl/lib/libssl.a /home/shamanin/tmp/libssh/openssl/lib/libcrypto.a -lsocket -lz -lnsl -lresolv -lposix4 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/libgcc.a */ #include <libssh/libssh.h> #include <libssh/server.h> #include <stdio.h> #include <sys/time.h> #include <strings.h> #include <errno.h> const int bindPort = 2222; const char* bindIp = "0.0.0.0"; const char* dsaKeyFile = "./ssh_host_dsa_key"; const char* rsaKeyFile = "./ssh_host_rsa_key"; int setKeys(ssh_bind bind) { if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY, dsaKeyFile) < 0) { printf("Cannot set DSA key file\n"); return -1; } if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, rsaKeyFile) < 0) { printf("Cannot set RSA key file\n"); return -1; } return 0; } int accept_ssh_connection(ssh_bind bind, ssh_session &retSession) { if ((retSession = ssh_new()) == NULL) { printf("Can't create ssh session\n"); return -1; } int ret = ssh_bind_accept(bind, retSession); // this call should be failed in test if (ret != SSH_OK) { ssh_disconnect(retSession); ssh_free(retSession); retSession = 0; printf("ssh_bind_accept failed: %s\n", ssh_get_error(bind)); return -1; } return 0; } int select_loop(ssh_bind bind, ssh_session &retSession) { ssh_channel channels[1], outchannels[1]; fd_set fds; int maxfd; struct timeval timeout; int listenFd = ssh_bind_get_fd(bind); timeout.tv_sec=300000; // long time timeout.tv_usec=0; channels[0] = 0; outchannels[0] = 0; FD_ZERO(&fds); FD_SET(listenFd,&fds); // in real application fds will contain additional descriptors of other sockets maxfd = listenFd + 1; int ret = SSH_OK; while (ret == SSH_OK) { printf("Wait for ssh_select\n"); ret = ssh_select(channels,outchannels,maxfd,&fds,&timeout); printf("ssh_select result: %d\n", ret); if (ret == SSH_OK && FD_ISSET(listenFd, &fds)) // is event on SSH listening descriptor { if (accept_ssh_connection(bind, retSession) < 0) { printf("Can't accept connection\n"); { char buf[32]; int rres = read(listenFd, buf, sizeof(buf)); printf("read %d bytes from failed socket\n", rres); } continue; // we can't accept incomming SSH connection for any reason, but we should listen descriptors for other events // problem is: ssh_select returns event for listening descriptor always, after fail in ssh_bind_accept //return -1; } else { printf("Connection was accepted\n"); } } } return 0; } void openFiles() { for(int i=0; i<10000; ++i) { char fname[128]; snprintf(fname, sizeof(fname), "delme%d", i); FILE* fp = fopen(fname, "w"); if (!fp) { int err = errno; printf("Max open file count was reached: can't open file %s (%d files opened). errno=%d, strerror: %s\n", fname, i+1, err, strerror(err)); if (i < 10) printf("++++ Few files were opened. May be test was reproducced incorrectly.\n"); return; } } } int main() { ssh_bind bind = 0; ssh_session session = 0; ssh_channel channel = 0; if(ssh_init() != 0) { printf("Can't init libssh\n"); return -1; } if ((bind = ssh_bind_new()) == NULL) { printf("ssh_bind_new error: %s\n",ssh_get_error(bind)); return -1; } if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, bindIp) < 0 || ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT, (void*) &bindPort) < 0) { printf("ssh_bind_options_set error: %s\n",ssh_get_error(bind)); return -1; } if (setKeys(bind) < 0) return -1; if (ssh_bind_listen(bind) < 0) { printf("ssh_bind_listen error: %s\n",ssh_get_error(bind)); return -1; } openFiles(); select_loop(bind, session); ssh_finalize(); return 0; }
Archive administrator: postmaster@lists.cynapses.org