]> code.citadel.org Git - citadel.git/blobdiff - citadel/sysdep.c
* Set CTDLEXIT_SHUTDOWN value to 0
[citadel.git] / citadel / sysdep.c
index d79785a5a5ebebf1d9dc93473ec9dce08f9eafdc..ac654ac52c1d171e06b19b1c572cb3426f11a6cb 100644 (file)
@@ -2,7 +2,7 @@
  * $Id$
  *
  * Citadel "system dependent" stuff.
- * See copyright.txt for copyright information.
+ * See COPYING for copyright information.
  *
  * Here's where we (hopefully) have most parts of the Citadel server that
  * would need to be altered to run the server in a non-POSIX environment.
@@ -548,9 +548,8 @@ void CtdlFillSystemContext(struct CitContext *context, char *name)
 }
 
 /*
- * The following functions implement output buffering. If the kernel supplies
- * native TCP buffering (Linux & *BSD), use that; otherwise, emulate it with
- * user-space buffering.
+ * The following functions implement output buffering on operating systems which
+ * support it (such as Linux and various BSD flavors).
  */
 #ifndef HAVE_DARWIN
 #ifdef TCP_CORK
@@ -563,64 +562,31 @@ void CtdlFillSystemContext(struct CitContext *context, char *name)
 #endif /* TCP_CORK */
 #endif /* HAVE_DARWIN */
 
-#ifdef HAVE_TCP_BUFFERING
 static unsigned on = 1, off = 0;
-void buffer_output(void) {
-       struct CitContext *ctx = MyContext();
-       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
-       ctx->buffering = 1;
-}
-
-void unbuffer_output(void) {
-       struct CitContext *ctx = MyContext();
-       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
-       ctx->buffering = 0;
-}
 
-void flush_output(void) {
-       struct CitContext *ctx = MyContext();
-       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
-       setsockopt(ctx->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
-}
-#else 
-#ifdef HAVE_DARWIN
-/* Stub functions for Darwin/OS X where TCP buffering isn't liked at all */
 void buffer_output(void) {
-       CC->buffering = 0;
-}
-void unbuffer_output(void) {
-       CC->buffering = 0;
-}
-void flush_output(void) {
-}
-#else
-void buffer_output(void) {
-       if (CC->buffering == 0) {
-               CC->buffering = 1;
-               CC->buffer_len = 0;
-               CC->output_buffer = malloc(SIZ);
+#ifdef HAVE_TCP_BUFFERING
+       if (!CC->redirect_ssl) {
+               setsockopt(CC->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
        }
+#endif
 }
 
-void flush_output(void) {
-       if (CC->buffering == 1) {
-               client_write(CC->output_buffer, CC->buffer_len);
-               CC->buffer_len = 0;
+void unbuffer_output(void) {
+#ifdef HAVE_TCP_BUFFERING
+       if (!CC->redirect_ssl) {
+               setsockopt(CC->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
        }
+#endif
 }
 
-void unbuffer_output(void) {
-       if (CC->buffering == 1) {
-               CC->buffering = 0;
-               /* We don't call flush_output because we can't. */
-               client_write(CC->output_buffer, CC->buffer_len);
-               CC->buffer_len = 0;
-               free(CC->output_buffer);
-               CC->output_buffer = NULL;
-       }
+void flush_output(void) {
+#ifdef HAVE_TCP_BUFFERING
+       struct CitContext *CCC = CC;
+       setsockopt(CCC->client_socket, IPPROTO_TCP, TCP_CORK, &off, 4);
+       setsockopt(CCC->client_socket, IPPROTO_TCP, TCP_CORK, &on, 4);
+#endif
 }
-#endif /* HAVE_DARWIN */
-#endif /* HAVE_TCP_BUFFERING */
 
 
 
@@ -651,19 +617,6 @@ int client_write(char *buf, int nbytes)
                return 0;
        }
 
-#ifndef HAVE_TCP_BUFFERING
-       /* If we're buffering for later, do that now. */
-       if (Ctx->buffering) {
-               old_buffer_len = Ctx->buffer_len;
-               Ctx->buffer_len += nbytes;
-               Ctx->output_buffer = realloc(Ctx->output_buffer, Ctx->buffer_len);
-               memcpy(&Ctx->output_buffer[old_buffer_len], buf, nbytes);
-               return 0;
-       }
-#endif
-
-       /* Ok, at this point we're not buffering.  Go ahead and write. */
-
 #ifdef HAVE_OPENSSL
        if (Ctx->redirect_ssl) {
                client_write_ssl(buf, nbytes);
@@ -707,9 +660,8 @@ int client_write(char *buf, int nbytes)
 
 
 /*
- * cprintf()  ...   Send formatted printable data to the client.   It is
- *               implemented in terms of client_write() but remains in
- *               sysdep.c in case we port to somewhere without va_args...
+ * cprintf()   Send formatted printable data to the client.
+ *             Implemented in terms of client_write() so it's technically not sysdep...
  */
 void cprintf(const char *format, ...) {   
        va_list arg_ptr;   
@@ -948,6 +900,9 @@ void graceful_shutdown(int signum) {
        exit(0);
 }
 
+int nFireUps = 0;
+int nFireUpsNonRestart = 0;
+pid_t ForkedPid = 1;
 
 /*
  * Start running as a daemon.
@@ -1003,31 +958,40 @@ void start_daemon(int unused) {
                        }
                        waitpid(current_child, &status, 0);
                }
-
                do_restart = 0;
-
+               nFireUpsNonRestart = nFireUps;
                /* Did the main process exit with an actual exit code? */
                if (WIFEXITED(status)) {
+               
+                       CtdlLogPrintf(CTDL_DEBUG, "\e[31m WIFEXITED! \e[0m\n");
 
                        /* Exit code 0 means the watcher should exit */
-                       if (WEXITSTATUS(status) == 0) {
+                       if (WEXITSTATUS(status) == CTDLEXIT_SHUTDOWN) {
+                               CtdlLogPrintf(CTDL_DEBUG, "\e[31m CTDLEXIT_SHUTDOWN \e[0m\n");
                                do_restart = 0;
                        }
 
                        /* Exit code 101-109 means the watcher should exit */
                        else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
+                               CtdlLogPrintf(CTDL_DEBUG, "\e[31m CTDLEXIT NO RESTART \e[0m\n");
                                do_restart = 0;
                        }
 
                        /* Any other exit code means we should restart. */
                        else {
+                               CtdlLogPrintf(CTDL_DEBUG, "\e[31m ANY OTHER EXIT CODE \e[0m\n");
                                do_restart = 1;
+                               nFireUps++;
+                               ForkedPid = current_child;
                        }
                }
 
                /* Any other type of termination (signals, etc.) should also restart. */
                else {
+                       CtdlLogPrintf(CTDL_DEBUG, "\e[31m NON-EXIT TERMINATION \e[0m\n");
                        do_restart = 1;
+                       nFireUps++;
+                       ForkedPid = current_child;
                }
 
        } while (do_restart);
@@ -1038,6 +1002,28 @@ void start_daemon(int unused) {
 
 
 
+void checkcrash(void)
+{
+       if (nFireUpsNonRestart != nFireUps)
+       {
+               StrBuf *CrashMail;
+
+               CrashMail = NewStrBuf();
+               CtdlLogPrintf (CTDL_ALERT, "----------------sending crash mail\n");
+               StrBufPrintf(CrashMail, 
+                            "Your CitServer is just recovering from an unexpected termination.\n"
+                            " this maybe the result of an error in citserver or an external influence.\n"
+                            " You can get more information on this by enabling coredumping; for more information see\n"
+                            " http://citadel.org/doku.php/faq:mastering_your_os:gdb#how.do.i.make.my.system.produce.core-files\n"
+                            " If you already did, the file you're looking for most probably is %score.%d\n"
+                            " Yours faithfully...",
+                            ctdl_run_dir, ForkedPid);
+               aide_message(ChrPtr(CrashMail), "Citadel server crashed.");
+               FreeStrBuf(&CrashMail);
+       }
+}
+
+
 /*
  * Generic routine to convert a login name to a full name (gecos)
  * Returns nonzero if a conversion took place