gfriloux / maelstrom

Fork of maelstrom : https://git.enlightenment.org/devs/discomfitor/maelstrom.git/
GNU Lesser General Public License v2.1
1 stars 1 forks source link

Azy : [Windows] Multiple HTTP queries failing will make ecore to enter an infinite error loop #1

Open gfriloux opened 7 years ago

gfriloux commented 7 years ago

If you try to query a webserver that is turned off, youll get a connection refused. If you do that often enough, you will end up with having ecore's mainloop to continuously call MsgWaitForMultipleObjects(), with the latter always returning an error, and GetLastError() returning 87 (Invalid parameters).

It will endlessly print the following error message : ERR:ecore ecore_main.c:2047 _ecore_main_win32_select() ( 87) Paramtre incorrect.

And the main loop wont let anything else happend.

Using ecore_con_url in the same context doesnt trigger any probleme, so it is unsure that the bug rely inside ecore, it might only be a consequence of whats being done inside azy.

gfriloux commented 7 years ago

The following example code triggers the bug :

/* i686-w64-mingw32-gcc -o query.exe query.c `pkg-config --libs --cflags azy eina ecore` */
#include <Eina.h>
#include <Ecore.h>
#include <Azy.h>

typedef struct _Query
{
   Azy_Client *cli;

   struct
   {
      Ecore_Event_Handler *connected,
                          *disconnected,
                          *transfer_progress;
   } ev;
} Query;

void query_free(Query *q);

Eina_Bool
query_event_transfer_progress(
   void    *data,
   int      type EINA_UNUSED,
   void    *ev)
{
   Query                              *q   = data;
   Azy_Event_Client_Transfer_Progress *dse = ev;
   size_t                              size;
   char                               *s;
   int                                 len;

   if (q->cli != dse->client)
     return EINA_TRUE;

   EINA_LOG_DBG("Receiving data");
   azy_client_close(dse->client);
   return EINA_TRUE;
}

Eina_Bool
query_event_disconnected(
   void    *data,
   int      type EINA_UNUSED,
   void    *ev)
{
   Query      *q      = data;
   Azy_Client *client = ev;

   if (q->cli != client)
     return EINA_TRUE;

   EINA_LOG_DBG("q[%p] client[%p]", q, client);

   query_free(q);
   return EINA_TRUE;
}

Eina_Bool
query_event_connected(
   void    *data,
   int      type EINA_UNUSED,
   void    *ev)
{
   Query        *q   = data;
   Azy_Client   *cli = ev;
   Azy_Net      *net;

   if (q->cli != cli)
      return EINA_TRUE;

   EINA_LOG_DBG("q[%p] client[%p]", q, cli);
   net = azy_client_net_get(cli);
   EINA_SAFETY_ON_NULL_GOTO(net, free_query);

   azy_net_protocol_set(net, AZY_NET_PROTOCOL_HTTP_1_0);
   azy_net_uri_set(net, "/");
   azy_client_blank(cli, AZY_NET_TYPE_POST, NULL, NULL, NULL);
   return EINA_TRUE;

free_query:
   query_free(q);
}

void
query_free(
   Query *q)
{
   if (q->ev.transfer_progress) ecore_event_handler_del(q->ev.transfer_progress);
   if (q->ev.disconnected)      ecore_event_handler_del(q->ev.disconnected);
   if (q->ev.connected)         ecore_event_handler_del(q->ev.connected);

   azy_client_free(q->cli);
   free(q);
}

Eina_Bool
_query_new(void *data)
{
   Query *q;
   Eina_Bool r;

   q = calloc(1, sizeof(Query));
   EINA_SAFETY_ON_NULL_RETURN_VAL(q, EINA_TRUE);

#define _EV(_a, _b, _c, _d)                                                    \
   _a = ecore_event_handler_add(AZY_EVENT_CLIENT_ ## _b, query_event_ ## _c, _d)

   _EV(q->ev.connected, CONNECTED, connected, q);
   EINA_SAFETY_ON_NULL_GOTO(q->ev.connected, free_q);

   _EV(q->ev.disconnected, DISCONNECTED, disconnected, q);
   EINA_SAFETY_ON_NULL_GOTO(q->ev.disconnected, free_q);

   _EV(q->ev.transfer_progress, TRANSFER_PROGRESS, transfer_progress, q);
   EINA_SAFETY_ON_NULL_GOTO(q->ev.transfer_progress, free_q);
#undef _EV

   q->cli = azy_client_new();
   EINA_SAFETY_ON_NULL_GOTO(q->cli, free_q);

   r = azy_client_host_set(q->cli, "192.168.4.110", 4333);
   EINA_SAFETY_ON_TRUE_GOTO(!r, free_q);

   r = azy_client_connect(q->cli);
   EINA_SAFETY_ON_TRUE_GOTO(!r, free_q);

   azy_client_timeout_set(q->cli, 10);
   return EINA_TRUE;

free_q:
   query_free(q);
   return EINA_TRUE;
}

int main(int argc, char **argv)
{
   azy_init();

   ecore_timer_add(1, _query_new, NULL);

   ecore_main_loop_begin();

   azy_shutdown();
   return 0;
}