Subject: Re: [libssh2] Does sftp work in a multi-threaded program?

Re: [libssh2] Does sftp work in a multi-threaded program?

From: Gutjahr, Troy <Troy.Gutjahr_at_tellabs.com>
Date: Thu, 31 May 2007 21:25:19 -0500

My previous post appeared in a strange format in the mailing list
archive. I guess I should have sent it in plain text. Here is is again.
I hope this is more readable.

-- Troy

==============================

Greetings.

How well is libssh2 supposed to work in multithreaded programs?

I'm using version libssh2-0.15-20070524, which is relatively recent. I
built it on Solaris 9 with the C compiler from Sun Studio 11.

Attached is a little program based on the example that demonstrates a
problem I have encountered. I build this program with Sun Studio 11's
C++ compiler because my goal is to use libssh2 in a C++ application.

The problem is that I can only establish an sftp session if I do it in
the main thread.

When I run the program with no command line parameters, it correctly
establishes an sftp session to a Solaris 10 server that is running the
Sun-provided sshd (which is a version of OpenSSH sshd). When I run the
program with a command line parameter, the program invokes the libssh2
calls in a different thread. In this case, it fails to establish an sftp
session.

I'm sure that I have read somewhere in the mailing list or discussion
forums that someone is using libssh2 and sftp in multithreaded
applications. It seems like I must be doing something wrong.

When my test program fails, it appears that the call to
_libssh2_channel_read(channel, (char *)buffer, 4) at line 235 of sftp.c
is returning -1 instead of the expected value of 4.

Does anyone have any suggestions?

Here is a portion of the output when it fails:

...

[libssh2] SFTP Subsystem: Initializing SFTP subsystem
[libssh2] Connection: Allocated new channel ID#0
[libssh2] Connection: Opening Channel - win 65536 pack 16384
=> libssh2_packet_write plain (24 bytes)
0000: 5a 00 00 00 07 73 65 73 73 69 6f 6e 00 00 00 00 Z....session....
0010: 00 01 00 00 00 00 40 00 ......@.
=> libssh2_packet_write send() (68 bytes)
0000: 9c b2 9e 42 71 e6 b4 a5 2b d3 8c 5b df c3 cc 4f ...Bq...+..[...O
0010: 0e ea b1 12 95 55 69 98 2f 03 16 2f e8 b5 22 e9 .....Ui./../..".
0020: ea 26 35 05 14 c4 31 47 a7 7b 97 0a 34 27 e5 da .&5...1G.{..4'..
0030: dd 6f 4f 07 e8 4a 80 b1 f3 1e a2 e9 df 68 ff cd .oO..J.......h..
0040: 14 11 cd ea ....
[libssh2] Transport: Looking for packet of type: 91
[libssh2] Transport: Looking for packet of type: 92
=> libssh2_packet_read() raw (52 bytes)
0000: b5 7c 2d dd b9 18 2b 86 6a 8a f0 0e 03 f5 0e 57 .|-...+.j......W
0010: ce 13 19 cb 45 41 8e c6 17 7c 29 36 06 06 d7 63 ....EA...|)6...c
0020: 16 d3 a8 b1 16 6a 00 f8 c1 0f 46 fe 21 48 24 69 .....j....F.!H$i
0030: 6e 90 b1 91 n...
=> libssh2_packet_read() plain (17 bytes)
0000: 5b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 [...............
0010: 00 .
[libssh2] Transport: Packet type 91 received, length=17
[libssh2] Transport: Looking for packet of type: 91
[libssh2] Connection: Connection Established - ID: 0/0 win: 0/65536
pack: 32768/16384
[libssh2] Connection: starting request(subsystem) on channel 0/0,
message=sftp
=> libssh2_packet_write plain (27 bytes)
0000: 62 00 00 00 00 00 00 00 09 73 75 62 73 79 73 74 b........subsyst
0010: 65 6d ff 00 00 00 04 73 66 74 70 em.....sftp
=> libssh2_packet_write send() (68 bytes)
0000: 93 7f aa 1f ba 1c 9f 34 95 f3 27 e0 64 6f da 82 ......4..'.do..
0010: 9c 4a a2 c8 16 dc ad 35 53 2b ad 39 8e 61 3d 13 .J.....5S+.9.a=.
0020: 6e 54 41 cd 58 8b 43 35 1b 69 ca b7 3c d3 1d b8 nTA.X.C5.i..<...
0030: c4 b7 0f 5e 8c 51 0b 64 ad dc f0 63 39 86 31 87 ...^.Q.d...c9.1.
0040: a9 f4 48 2b ..H+
[libssh2] Transport: Looking for packet of type: 99
[libssh2] Transport: Looking for packet of type: 100
=> libssh2_packet_read() raw (88 bytes)
0000: 46 25 6e 00 52 76 d6 3f dd 7b ed 57 49 af b1 ae F%n.Rv.?.{.WI...
0010: dc 78 19 b2 9a 53 d7 53 3a 54 be 46 11 f4 e4 eb .x...S.S:T.F....
0020: a8 6f 70 72 83 9e 96 46 eb c6 37 19 9c 7b c5 39 .opr...F..7..{.9
0030: c4 82 d0 f0 2f 5a 30 73 e6 e6 8c e8 9d 4f 35 5e ..../Z0s.....O5^
0040: 1e e1 02 a0 6d 70 95 71 4c f7 83 8a 7e f8 19 6c ....mp.qL...~..l
0050: f7 b7 13 1a aa 60 1d 9d .....`..
=> libssh2_packet_read() plain (9 bytes)
0000: 5d 00 00 00 00 00 02 00 00 ]........
[libssh2] Transport: Packet type 93 received, length=9
[libssh2] Connection: Window adjust received for channel 0/0, adding
131072 bytes, new window_size=131072
=> libssh2_packet_read() plain (5 bytes)
0000: 63 00 00 00 00 c....
[libssh2] Transport: Packet type 99 received, length=5
[libssh2] Transport: Looking for packet of type: 99
[libssh2] Connection: Setting blocking mode on channel 0/0 to 1
[libssh2] Connection: Setting channel 0/0 handle_extended_data mode to 1
[libssh2] SFTP Subsystem: Sending FXP_INIT packet advertising version 3
support
[libssh2] Connection: Setting blocking mode on channel 0/0 to 1
[libssh2] Connection: Writing 9 bytes on channel 0/0, stream #0
[libssh2] Connection: Sending 9 bytes on channel 0/0, stream_id=0
=> libssh2_packet_write plain (18 bytes)
0000: 5e 00 00 00 00 00 00 00 09 00 00 00 05 01 00 00 ^...............
0010: 00 03 ..
=> libssh2_packet_write send() (52 bytes)
0000: ea 1c ae ba cd e8 ac f6 66 c2 00 8c 99 6c f3 e2 ........f....l..
0010: b5 3f 86 5a b7 02 e3 5b f2 78 fa 86 c4 61 98 88 .?.Z...[.x...a..
0020: ab 71 db 20 5b 44 00 bc 17 95 86 5e c2 a1 17 83 .q. [D.....^....
0030: be 7a a6 f4 .z..
[libssh2] Connection: Setting blocking mode on channel 0/0 to 1
[libssh2] SFTP Subsystem: Requiring 2 packet
[libssh2] SFTP Subsystem: Asking for 2 packet
[libssh2] SFTP Subsystem: Waiting for packet: will block
[libssh2] Connection: Setting blocking mode on channel 0/0 to 1
[libssh2] Connection: Attempting to read 4 bytes from channel 0/0 stream
#0
[libssh2] Connection: Setting blocking mode on channel 0/0 to 0
[libssh2] Failure Event: -30 - Timeout waiting for FXP packet
[libssh2] Failure Event: -30 - Timeout waiting for response from SFTP
subsystem
[libssh2] Connection: Freeing channel 0/0 resources
[libssh2] Connection: Closing channel 0/0
=> libssh2_packet_write plain (5 bytes)
0000: 61 00 00 00 00 a....
=> libssh2_packet_write send() (36 bytes)
0000: 4f 89 cb 97 da 37 be 42 ab 63 ed 83 a9 76 26 fd O....7.B.c...v&.
0010: d1 c6 45 d9 e6 0c 01 88 89 e3 2b 38 60 d3 cf 81 ..E.......+8`...
0020: 95 8e 7c 35 ..|5
[libssh2] Connection: Setting blocking mode on channel 0/0 to 1

Here is the program:

#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include "libssh2.h"
#include "libssh2_sftp.h"

void
try_sftp()
{
    std::cout << "**** try_sftp started" << std::endl;

    int sock;
    struct sockaddr_in sin;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    sin.sin_family = AF_INET;
    sin.sin_port = htons(22);
    // 172.28.15.12 = 0xAC1C0F0C
    sin.sin_addr.s_addr = htonl(0xAC1C0F0C);
    if (connect(sock,
                (struct sockaddr*)(&sin),
                sizeof(struct sockaddr_in)) != 0)
    {
        std::cerr << "**** failed to connect!" << std::endl;
        return;
    }

    LIBSSH2_SESSION *session;
    session = libssh2_session_init();
    if (libssh2_session_startup(session, sock))
    {
        std::cerr << "**** failed to establish SSH session" <<
std::endl;
        return;
    }

    libssh2_trace(session, 255);

    char userid[] = "troyg";
    char password[] = "troyg.1";

    if (libssh2_userauth_password(session, userid, password))
    {
        std::cerr << "**** authentication by password failed" <<
std::endl;
        goto shutdown;
    }
    else
    {
        std::cout << "**** successfully authenticated as user " <<
userid << std::endl;
    }

    LIBSSH2_SFTP *sftp;
    sftp = libssh2_sftp_init(session);
    if (sftp)
    {
        std::cout << "**** established SFTP session." << std::endl;
    }
    else
    {
        std::cerr << "**** failed to establish SFTP session." <<
std::endl;
        goto shutdown;
    }

shutdown_ftp:
    if (libssh2_sftp_shutdown(sftp) == 0)
    {
        std::cout << "**** terminated SFTP session." << std::endl;
    }
    else
    {
        std::cerr << "**** failed to terminate SFTP session." <<
std::endl;
    }
shutdown:
    libssh2_session_disconnect(session, "Normal Shutdown, Thank you for
playing");
    libssh2_session_free(session);
    close(sock);
}

void *
thread_main(void *)
{
    try_sftp();
    return NULL;
}

int
main( int argc, char *argv[] )
{
    if (argc > 1)
    {
        pthread_t threadID;

        pthread_create(&threadID, NULL, thread_main, NULL);
        sleep(10000);
    }
    else
    {
        try_sftp();
    }
    return 0;
}

Thanks in advance for any help you can offer.

Troy Gutjahr
Staff Engineer
Tellabs Inc.
============================================================
The information contained in this message may be privileged
and confidential and protected from disclosure. If the reader
of this message is not the intended recipient, or an employee
or agent responsible for delivering this message to the
intended recipient, you are hereby notified that any reproduction,
dissemination or distribution of this communication is strictly
prohibited. If you have received this communication in error,
please notify us immediately by replying to the message and
deleting it from your computer. Thank you. Tellabs
============================================================

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
libssh2-devel mailing list
libssh2-devel_at_lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libssh2-devel
Received on 2007-06-01