morgon has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I need to pass an IO::Socket::SSL instance from one thread to another to fix a poorly designed script that I don't have the time to rewrite.

Directly sharing it is not possible (you get an error that it is not sharable) so at the moment I am trying to share the underlying file-descriptor but I am having problems re-creating an IO::Socket::SSL instance in the other thread.

I have tried this:

my $socket_fd :shared; # in one thread $socket_fd = $ssl_socket->fileno; # in another thread my $ssl_socket = IO::Handler->new_from_fd($socket_fd, "r");
but that only gives me an IO::Handle-instance and I don't understand the second argument of new_from_fd at all (I had assumed that if I needed to use a mode of "rw" but that raises an error or "invalid mode").

To get an instance of the proper class I have tried

my $ssl_socket = IO::Socket::SLL->new_from_fd($socket_fd, "r");
but that only gets me an undef.

So evidently I don't have a clue on how to do this if it is possible at all - can someone please help me here?

Many thanks!

Replies are listed 'Best First'.
Re: Passing SSL-socket among threads
by wrog (Friar) on Mar 19, 2012 at 20:26 UTC
    A quick perusal of the IO::Socket::SSL POD reveals that
    1. new_from_fd explicitly ignores its mode argument so you may as well leave it off
    2. You can use IO::Socket::SSL::errstr() immediately after the new_from_fd to see what went wrong (or at least, given that you're getting undef back from IO::Socket::SSL->new_from_fd, you should get the text of some error message, whether this has direct bearing on the problem or not...)
    3. This module is not thread-safe, so basically all bets are off. While it admits some possibility of working if you're not using SSL_verify_callback or SSL_password_cb, I'd say the bottom line here is that since the module author has evidently not done the work to make sure IO::Socket::SSL can be used across threads, there's probably a reason, i.e., something that was too difficult to deal with in C code, that you're clearly not going to be able to address from pure Perl, and unless the previous two points turn up something obvious that you can fix and that happens to work (that you may still not want to trust), you'll probably want to try some completely different approach
    update:
    I'm also skeptical that new_from_fd could ever actually do what you want, since an SSL connection has a huge pile of state associated with it, e.g., the choice of cipher, the actual keys in use, etc... information that simply cannot be derived from the underlying file descriptor; you have to copy it in from the handle object in the other thread somehow. As far as I can tell, a new_from_fd call from another thread on an already-open socket would have to renegotiate a new SSL session from scratch.

    Oddly enough, copying of a structure like IO::Handle/Socket happens automatically when you create a new thread. And this tends to work fine in the case of a pure perl structure, in which case referring to the same variable in a different thread will refer to the clone and you're done.

    But when you have an object created directly by C code, then you'll have an underlying C structure, and unless the module author explicitly did something about this — what it means to make the module thread-safe — the C structure will be shared by the various perl clones, which are all assuming they each have the C structure all to themselves, at which point things will go to hell the first time you use the object from a different thread (i.e., because it's a different clone with the wrong perl state).

    The only way this has any chance of working is if you exclusively use the handle object in the parent thread prior to the child thread being created, never use it in the parent thread thereafter (not even to close it), always use it from that child thread from then on, closing it from that child thread once you're done with it.

    And if this usage pattern doesn't fit the design of your code, you're going to lose...)