#285: multithread calls libssh2.a error -----------------------------------------------------+-------------------- Reporter: beiguan001 | Owner: Type: defect | Status: new Priority: high | Milestone: 1.4.3 Component: API | Version: 1.4.2 Keywords: multi-thread libssh2_session_handshake | Blocked By: Blocks: | -----------------------------------------------------+-------------------- When using multiple threads, in libssh2_session_handshake abnormal. If you do not multi-threaded, no problem. How to use multi-thread calls libssh2?
//////////// main cpp////////// void* work_thread(void* arg) { string ipaddr = "132.31.0.13"; string user = "user"; string passwd = "pass"; int port = 22; Ssh2Client ssh3; ssh3.setHost(ipaddr.c_str(), user.c_str(), passwd.c_str(), port); ssh3.setTimeOut(10000L);//10s if(ssh3.ssh2_connect() < 0) cout << "Error : connect error!" << endl; if(ssh3.ssh2_open_session() < 0) { cout << "Error : ssh2_open_session error!" << endl; exit(0); } } int main(int argc,char* argv[]) { int nthread = 1; pthread_t tid; for(int i=0;i<nthread;i++) { pthread_create(&tid,NULL,work_thread,NULL); } } //////////////////////Ssh2Client.cpp void Ssh2Client::setHost(const char *host, const char *user, const char *passwd, int pt) { hostname = host; username = user; password = passwd; port = pt; } int Ssh2Client::ssh2_connect() { int rc = 0; unsigned long hostaddr; struct sockaddr_in sin; #ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #endif rc = libssh2_init(0); if (rc != 0) { sprintf(errmsg, "libssh2 initialization failed (%d)\n", rc); return -1; } thread_setup(); hostaddr = inet_addr(hostname); sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(port); sin.sin_addr.s_addr = hostaddr; if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { sprintf(errmsg, "failed to connect!\n"); return -1; } return 0; } int Ssh2Client::ssh2_open_session() { int rc = 0; size_t len; LIBSSH2_KNOWNHOSTS *nh; int type; const char *fingerprint; /* Create a session instance */ session = libssh2_session_init(); if (!session) return -1; // libssh2_session_set_timeout(session, timeout); /* tell libssh2 we want it all done non-blocking */ // libssh2_session_set_blocking(session, block); /* ... start it up. This will trade welcome banners, exchange keys, * and setup crypto, compression, and MAC layers */ while ((rc = libssh2_session_handshake(session, sock)) == LIBSSH2_ERROR_EAGAIN); if (rc) { printf("File = %s, Line = %d, rc = %d\n", __FILE__, __LINE__, rc); sprintf(errmsg, "Failure establishing SSH session: %d\n", rc); return -1; } nh = libssh2_knownhost_init(session); if(!nh) { /* eeek, do cleanup here */ return -2; } /* read all hosts from here */ libssh2_knownhost_readfile(nh, "known_hosts", LIBSSH2_KNOWNHOST_FILE_OPENSSH); /* store all known hosts to here */ libssh2_knownhost_writefile(nh, "dumpfile", LIBSSH2_KNOWNHOST_FILE_OPENSSH); fingerprint = libssh2_session_hostkey(session, &len, &type); if(fingerprint) { struct libssh2_knownhost *host; #if LIBSSH2_VERSION_NUM >= 0x010206 /* introduced in 1.2.6 */ int check = libssh2_knownhost_checkp(nh, hostname, 22, fingerprint, len, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW, &host); #else /* 1.2.5 or older */ int check = libssh2_knownhost_check(nh, hostname, fingerprint, len, LIBSSH2_KNOWNHOST_TYPE_PLAIN| LIBSSH2_KNOWNHOST_KEYENC_RAW, &host); #endif sprintf(errmsg, "Host check: %d, key: %s\n", check, (check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)? host->key:"<none>"); /***** * At this point, we could verify that 'check' tells us the key is * fine or bail out. *****/ } else { /* eeek, do cleanup here */ return -3; } libssh2_knownhost_free(nh); if ( strlen(password) != 0 ) { /* We could authenticate via password */ while ((rc = libssh2_userauth_password(session, username, password)) == LIBSSH2_ERROR_EAGAIN); if (rc) { sprintf(errmsg, "Authentication by password failed.\n"); ssh2_free_session(); ssh2_close(); return -1; } } else { /* Or by public key */ char *home = getenv("HOME"); if(home == NULL) { sprintf(errmsg,"HOME not defined\n"); return -1; } char path1[1024]; char path2[1024]; strcat(path1,home); strcat(path1,"/.ssh/id_rsa.pub"); strcat(path2,home); strcat(path2,"/.ssh/id_rsa"); free(home); while ((rc = libssh2_userauth_publickey_fromfile(session,username,path1,path2,password)) == LIBSSH2_ERROR_EAGAIN); if (rc) { sprintf(errmsg, "\tAuthentication by public key failed\n"); ssh2_free_session(); ssh2_close(); return -1; } } return 0; } /////////////////////////////////////////////////////// -- Ticket URL: <https://trac.libssh2.org/ticket/285> libssh2 <https://trac.libssh2.org/> C library for writing portable SSH2 clients _______________________________________________ libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel