properly abort if we fail to create debug files instead of crashing.
[citadel.git] / citadel / event_client.c
index c46429337da7f1db65dff1b53db14ea916679d38..999c9e4546c1b989efc6fb93c6f6ab8df8394b8f 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "ctdl_module.h"
 #include "event_client.h"
+#include "citserver.h"
 
 ConstStr IOStates[] = {
        {HKEY("DB Queue")},
@@ -68,7 +69,7 @@ void SetEVState(AsyncIO *IO, eIOState State)
 
 }
 
-
+eNextState QueueAnEventContext(AsyncIO *IO);
 static void IO_Timeout_callback(struct ev_loop *loop, ev_timer *watcher, int revents);
 static void IO_abort_shutdown_callback(struct ev_loop *loop,
                                       ev_cleanup *watcher,
@@ -86,7 +87,7 @@ extern struct ev_loop *event_db;
 extern ev_async DBAddJob;
 extern ev_async DBExitEventLoop;
 
-eNextState QueueDBOperation(AsyncIO *IO, IO_CallBack CB)
+eNextState QueueAnDBOperation(AsyncIO *IO)
 {
        IOAddHandler *h;
        int i;
@@ -94,7 +95,10 @@ eNextState QueueDBOperation(AsyncIO *IO, IO_CallBack CB)
        SetEVState(IO, eDBQ);
        h = (IOAddHandler*)malloc(sizeof(IOAddHandler));
        h->IO = IO;
-       h->EvAttch = CB;
+
+       assert(IO->ReAttachCB != NULL);
+
+       h->EvAttch = IO->ReAttachCB;
        ev_cleanup_init(&IO->db_abort_by_shutdown,
                        IO_abort_shutdown_callback);
        IO->db_abort_by_shutdown.data = IO;
@@ -161,12 +165,15 @@ DB_PerformNext(struct ev_loop *loop, ev_idle *watcher, int revents)
        assert(IO->NextDBOperation);
        switch (IO->NextDBOperation(IO))
        {
+       case eSendReply:
+               ev_cleanup_stop(loop, &IO->db_abort_by_shutdown);
+               QueueAnEventContext(IO);
+               break;
        case eDBQuery:
                break;
        case eSendDNSQuery:
        case eReadDNSReply:
        case eConnect:
-       case eSendReply:
        case eSendMore:
        case eSendFile:
        case eReadMessage:
@@ -219,7 +226,7 @@ static void IO_abort_shutdown_callback(struct ev_loop *loop,
 }
 
 
-eNextState QueueEventContext(AsyncIO *IO, IO_CallBack CB)
+eNextState QueueAnEventContext(AsyncIO *IO)
 {
        IOAddHandler *h;
        int i;
@@ -227,7 +234,11 @@ eNextState QueueEventContext(AsyncIO *IO, IO_CallBack CB)
        SetEVState(IO, eIOQ);
        h = (IOAddHandler*)malloc(sizeof(IOAddHandler));
        h->IO = IO;
-       h->EvAttch = CB;
+
+       assert(IO->ReAttachCB != NULL);
+
+       h->EvAttch = IO->ReAttachCB;
+
        ev_cleanup_init(&IO->abort_by_shutdown,
                        IO_abort_shutdown_callback);
        IO->abort_by_shutdown.data = IO;
@@ -260,12 +271,20 @@ eNextState QueueEventContext(AsyncIO *IO, IO_CallBack CB)
 eNextState EventQueueDBOperation(AsyncIO *IO, IO_CallBack CB, int CloseFDs)
 {
        StopClientWatchers(IO, CloseFDs);
-       return QueueDBOperation(IO, CB);
+       IO->ReAttachCB = CB;
+       return eDBQuery;
 }
 eNextState DBQueueEventContext(AsyncIO *IO, IO_CallBack CB)
 {
        StopDBWatchers(IO);
-       return QueueEventContext(IO, CB);
+       IO->ReAttachCB = CB;
+       return eSendReply;
+}
+
+eNextState QueueEventContext(AsyncIO *IO, IO_CallBack CB)
+{
+       IO->ReAttachCB = CB;
+       return QueueAnEventContext(IO);
 }
 
 extern eNextState evcurl_handle_start(AsyncIO *IO);
@@ -310,7 +329,8 @@ eNextState QueueCurlContext(AsyncIO *IO)
 eNextState CurlQueueDBOperation(AsyncIO *IO, IO_CallBack CB)
 {
        StopCurlWatchers(IO);
-       return QueueDBOperation(IO, CB);
+       IO->ReAttachCB = CB;
+       return eDBQuery;
 }
 
 
@@ -379,7 +399,7 @@ void StopCurlWatchers(AsyncIO *IO)
        IO->RecvBuf.fd = 0;
 }
 
-void ShutDownCLient(AsyncIO *IO)
+eNextState ShutDownCLient(AsyncIO *IO)
 {
        CitContext *Ctx =IO->CitContext;
 
@@ -399,11 +419,12 @@ void ShutDownCLient(AsyncIO *IO)
                IO->DNS.Channel = NULL;
        }
        assert(IO->Terminate);
-       IO->Terminate(IO);
+       return IO->Terminate(IO);
 }
 
 void PostInbound(AsyncIO *IO)
 {
+
        switch (IO->NextState) {
        case eSendFile:
                ev_io_start(event_base, &IO->send_event);
@@ -425,6 +446,7 @@ void PostInbound(AsyncIO *IO)
                        break;
                case eDBQuery:
                        StopClientWatchers(IO, 0);
+                       QueueAnDBOperation(IO);
                default:
                        break;
                }
@@ -435,17 +457,18 @@ void PostInbound(AsyncIO *IO)
                ev_io_start(event_base, &IO->recv_event);
                break;
        case eTerminateConnection:
-               ShutDownCLient(IO);
-               break;
        case eAbort:
-               ShutDownCLient(IO);
+               if (ShutDownCLient(IO) == eDBQuery) {
+                       QueueAnDBOperation(IO);
+               }
                break;
        case eSendDNSQuery:
        case eReadDNSReply:
-       case eDBQuery:
        case eConnect:
        case eReadMessage:
                break;
+       case eDBQuery:
+               QueueAnDBOperation(IO);
        }
 }
 eReadState HandleInbound(AsyncIO *IO)
@@ -493,17 +516,16 @@ eReadState HandleInbound(AsyncIO *IO)
                }
 
                if (Finished != eMustReadMore) {
-                       eNextState rc;
-                       assert(IO->ReadDone);
                        ev_io_stop(event_base, &IO->recv_event);
-                       rc = IO->ReadDone(IO);
-                       if  (rc != eDBQuery) {
-                               IO->NextState = rc;
-                               Finished = StrBufCheckBuffer(&IO->RecvBuf);
+                       IO->NextState = IO->ReadDone(IO);
+                       if  (IO->NextState == eDBQuery) {
+                               if (QueueAnDBOperation(IO) == eAbort)
+                                       return eReadFail;
+                               else
+                                       return eReadSuccess;
                        }
                        else {
-                               return rc;
-
+                               Finished = StrBufCheckBuffer(&IO->RecvBuf);
                        }
                }
        }
@@ -541,6 +563,11 @@ IO_send_callback(struct ev_loop *loop, ev_io *watcher, int revents)
                         IO->SendBuf.fd);
 
                fd = fopen(fn, "a+");
+               if (fd == NULL) {
+                       syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno));
+                       cit_backtrace();
+                       exit(1);
+               }
                fprintf(fd, "Send: BufSize: %ld BufContent: [",
                        nbytes);
                rv = fwrite(pchh, nbytes, 1, fd);
@@ -864,6 +891,11 @@ IO_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents)
                         IO->SendBuf.fd);
 
                fd = fopen(fn, "a+");
+               if (fd == NULL) {
+                       syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno));
+                       cit_backtrace();
+                       exit(1);
+               }
                fprintf(fd, "Read: BufSize: %ld BufContent: [",
                        nbytes);
                rv = fwrite(pchh, nbytes, 1, fd);
@@ -912,9 +944,18 @@ IO_postdns_callback(struct ev_loop *loop, ev_idle *watcher, int revents)
                case eAbort:
 ////                   StopClientWatchers(IO);
                        ShutDownCLient(IO);
+                       break;
+               case eDBQuery:
+                       StopClientWatchers(IO, 0);
+                       QueueAnDBOperation(IO);
+                       break;
                default:
                        break;
                }
+       case eDBQuery:
+               StopClientWatchers(IO, 0);
+               QueueAnDBOperation(IO);
+               break;
        default:
                break;
        }
@@ -1199,8 +1240,13 @@ eNextState KillOtherContextNow(AsyncIO *IO)
 
        SetEVState(IO, eKill);
 
-       if (Ctx->OtherOne->ShutdownAbort != NULL)
-               Ctx->OtherOne->ShutdownAbort(Ctx->OtherOne);
+       if (Ctx->OtherOne->ShutdownAbort != NULL) {
+               Ctx->OtherOne->NextState = eAbort;
+               if (Ctx->OtherOne->ShutdownAbort(Ctx->OtherOne) == eDBQuery) {
+                       StopClientWatchers(Ctx->OtherOne, 0);
+                       QueueAnDBOperation(Ctx->OtherOne);
+               }
+       }
        return eTerminateConnection;
 }
 
@@ -1239,10 +1285,12 @@ void KillAsyncIOContext(AsyncIO *IO)
        case eReadMore:
        case eReadPayload:
        case eReadFile:
-               QueueEventContext(&Ctx->IO, KillOtherContextNow);
+               Ctx->IO.ReAttachCB = KillOtherContextNow;
+               QueueAnEventContext(&Ctx->IO);
                break;
        case eDBQuery:
-               QueueDBOperation(&Ctx->IO, KillOtherContextNow);
+               Ctx->IO.ReAttachCB = KillOtherContextNow;
+               QueueAnDBOperation(&Ctx->IO);
                break;
        case eTerminateConnection:
        case eAbort: