Hello,
Maybe there is an other issue in 0.9.49. It works with 0.9.48.
The attached testcase tries to:
a) create a socket on port 8080
b) a connection is suspended
c) a thread waits a second, then resumes the connection
d) error: the connection is never resumed (third call).
OS: Ubuntu gnome 15.10, Linux 4.2
My comandline:
g++ -o testmhd test.cpp -I/tmp/libmicrohttpd-0.9.49/src/include/
-L/tmp/libmicrohttpd-0.9.49/src/microhttpd/.libs/ -lmicrohttpd -pthread
LD_LIBRARY_PATH=/tmp/libmicrohttpd-0.9.49/src/microhttpd/.libs/
./testmhd
wget -O /dev/null 127.0.0.1:8080
Thanks a lot
Markus
Am Samstag, den 09.04.2016, 16:39 +0200 schrieb Christian Grothoff:
> Dear all,
>
> I'm happy to announce the release of libmicrohttpd 0.9.49.
>
> GNU libmicrohttpd is a small C library that is supposed to make it
> easy
> to run an HTTP server as part of another application. GNU
> libmicrohttpd
> is fully HTTP 1.1 compliant and supports IPv6. Finally, GNU
> libmicrohttpd is fast, portable and has a simple API and (without TLS
> support and other optional features) a small binary size (~32k).
>
>
> Major changes include:
>
> * use US-ASCII only (instead of user locale settings) when performing
> caseless string comparison.
> * Send response properly if sendfile() failed with EINVAL
> * do not crash if pthread_create() fails
> * various minor bugfixes (see ChangeLog)
> * use non-blocking sockets on all platforms
> * various improvements to the documentation
> * reducing number of system calls
>
> You can download GNU libmicrohttpd from
>
> * ftp://ftp.gnu.org/gnu/libmicrohttpd/ and all GNU FTP mirrors.
> * Our Subversion repository at https://gnunet.org/svn/libmicrohttpd/
>
> Please report bugs to our bugtracker at https://gnunet.org/bugs/.
>
> The documentation (including a reference manual and tutorial) can be
> found at http://www.gnu.org/software/libmicrohttpd/.
>
>
> Happy hacking!
>
> Christian & Evgeny
>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <microhttpd.h>
static void* wait_a_second_and_resume( void *arg )
{
fprintf( stderr, "thread: wait a second\n" );
sleep( 1 );
fprintf( stderr, "thread: resume connection\n" );
struct MHD_Connection *connection = (struct MHD_Connection *)arg;
MHD_resume_connection( connection );
return NULL;
}
static int http_AccessHandlerCallback( void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls )
{
// Do never respond on first call (especially POST wait for "100 Continue")
if( *con_cls == NULL )
{
fprintf( stderr, "callback: first call\n" );
int *status = (int*) malloc( sizeof(int) );
*status = 0;
*con_cls = status;
return MHD_YES;
}
int *status = (int*)*con_cls;
// Second call: create a thead and suspend connection
if( *status == 0 )
{
fprintf( stderr, "callback: second call\n" );
*status = 1;
MHD_suspend_connection( connection );
pthread_t thread_id;
pthread_attr_t thread_attr;
pthread_attr_init( &thread_attr );
pthread_create( &thread_id, &thread_attr, wait_a_second_and_resume, connection );
return MHD_YES;
}
// Third call: create response
{
fprintf( stderr, "callback: third call\n" );
static char html[] = "<html>\n"
"<head><title>Response</title></head>\n"
"<body><center><h1>Response</h1></center></body>\n"
"</html>\n";
struct MHD_Response *response = MHD_create_response_from_buffer( strlen(html), html, MHD_RESPMEM_PERSISTENT );
MHD_queue_response( connection, MHD_HTTP_OK, response );
MHD_destroy_response( response );
return MHD_YES;
}
}
int main()
{
// create a socket on port 8080
int ai_family = AF_INET;
struct sockaddr addr_socket;
struct sockaddr_in *in_addr = (struct sockaddr_in *) &addr_socket;
memset( in_addr, 0, sizeof(*in_addr) );
in_addr->sin_family = AF_INET;
in_addr->sin_port = htons( 8080 );
in_addr->sin_addr.s_addr = htonl( INADDR_ANY );
socklen_t addr_len = sizeof(*in_addr);
// Create socket
int listening_socket = socket( ai_family, SOCK_STREAM, IPPROTO_TCP );
if( listening_socket == -1 )
{
fprintf( stderr, "Could not create socket: %s.\n", strerror(errno) );
return EXIT_FAILURE;
}
// Non blocking socket
int file_descriptor_flag = fcntl( listening_socket, F_GETFL );
fcntl( listening_socket, F_SETFL, file_descriptor_flag | O_NONBLOCK );
// Bind socket
int bound = bind( listening_socket, &addr_socket, addr_len );
if( bound == -1 )
{
close( listening_socket );
fprintf( stderr, "Bind failed: %s\n", strerror(errno) );
return EXIT_FAILURE;
}
// Start listening
int listening = listen( listening_socket, 31 );
if( listening == -1 )
{
close( listening_socket );
fprintf( stderr, "Listen failed: %s\n", strerror(errno) );
return EXIT_FAILURE;
}
// Create daemon
unsigned int daemon_flags = MHD_USE_SELECT_INTERNALLY | MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_SUSPEND_RESUME | MHD_USE_PIPE_FOR_SHUTDOWN;
struct MHD_OptionItem options[] =
{
{ MHD_OPTION_LISTEN_SOCKET, listening_socket, NULL },
{ MHD_OPTION_THREAD_POOL_SIZE, 1, NULL },
{ MHD_OPTION_END, 0, NULL }
};
struct MHD_Daemon *daemon = MHD_start_daemon( daemon_flags, 0,
NULL, NULL,
http_AccessHandlerCallback, NULL,
MHD_OPTION_ARRAY, options,
MHD_OPTION_END );
if( daemon == NULL )
return EXIT_FAILURE;
sleep( 10000 );
// Stop daemon
MHD_stop_daemon( daemon );
return EXIT_SUCCESS;
}