help-gnutls
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gnutls_handshake() thread problem


From: Jay Anra
Subject: Re: gnutls_handshake() thread problem
Date: Mon, 22 Nov 2010 09:42:03 +0000

OK
I install a signal handler for SIGIO - call it sig_handler() and then open a socket and make it asynchronous and non-blocking. The program then goes to sleep waiting for the server to respond.

I am using the GNUTLS library for ftp (FTPeS) transfers so, as soon as the TCP/IP connection is established with the ftp server, the server responds with a 220 'hello' message.

When the 220 message arrives, my program receives the SIGIO and the sig_handler function is automatically invoked. I use the sig_handler() function to send back an 'AUTH TLS' message requesting that the server sets up TLS encryption on the connection. This is done just in the sig_handler() function which is effectively an interrupt handler, and does not 'wake up' the main thread. when the AUTH TLS message has been sent, the interrupt terminates and the program goes back to sleep.

The server responds with a 234 message accepting TLS as a method of encryption. At this point the main thread is woken up to start the handshake process and it calls gnutls_handshake(). As it's using a non-blocking socket, it returns immediately and the main thread goes to sleep waiting for a response from the server. The handshake response from the server is received and triggers the sig_handler() again which this time calls gnutls_handshake() to continue the handshake process, this goes on until the handshake is complete. When the handshake is complete, the main thread is woken up again to start the authentication.

The interrupt that was triggered by the servers response was causing sig_handler() and hence gnutls_handshake() to be called before the previous call to gnutls_handshake() (from the initial call from the main thread) had completed. I am running the code on a busy server so I am at the mercy of the scheduler and sometimes the thread running the previous call to gnutls_handshake() was 'swapped out' when the interrupt arrived. So, when my process next got CPU time, it was the interrupt that ran and not the end of the gnutls_handshake() call.

I assume you would not normally expect a remote host to respond to a block of handshake data without  the call to gnutls_handshake() that sent the previous block of data to the server, to have completed.  The scheduler on a busy machine together with asynchronous, non-blocking sockets add the possibility of unintentionally adding a virtual thread to the program with the sig_handler function, and calling gnutls_handshake concurrently.

There are numerous reasons why I have coded this the way I have.  There are any number of ways to stop this concurrency happening, masking signals, mutexes, putting the call to gnutls_handshake() in a while loop in the main thread etc, but unless you know that it's needed, you don't put it in because it's added complexity in the program.

regards

Jay



On Fri, Nov 19, 2010 at 3:07 PM, Nikos Mavrogiannopoulos <address@hidden> wrote:
On 11/19/2010 03:46 PM, Jay Anra wrote:
> answering your question: 'Do you call  gnutls_handshake in parallel from
> different threads?'
>
> Sort of, although not explicitly. It's a consequence of using asynchronous
> sockets. The concurrency comes
> from the interrupt generated by the SIGIO signal, which gets sent to my
> process when data arrives on the socket.
> Obviously I have no control over the timing of this signal, so it may cause
> concurrent calls to gnutls_handshake()
> or it may not.

I still cannot understand why you need to call gnutls_handshake() in a
concurrent way. Could you explain your scenario? In any case all gnutls
functions are reentrant as long as each session is handled in a single
thread.

regards,
Nikos


reply via email to

[Prev in Thread] Current Thread [Next in Thread]