Better error reports on internal handled errors.
authorviric@llimona
Thu, 05 Apr 2007 21:45:25 +0200
changeset 92 05004c52ecff
parent 91 0e8ef3d34b61
child 93 332574eacf8a
Better error reports on internal handled errors.
Makefile
client.c
client_run.c
error.c
execute.c
jobs.c
mail.c
main.c
main.h
msg.c
msgdump.c
server.c
server_start.c
ts.1
--- a/Makefile	Thu Apr 05 19:19:09 2007 +0200
+++ b/Makefile	Thu Apr 05 21:45:25 2007 +0200
@@ -10,7 +10,8 @@
 	execute.o \
 	msg.o \
 	client_run.o \
-	mail.o
+	mail.o \
+	error.o
 INSTALL=/usr/bin/install -c
 
 all: ts
@@ -29,6 +30,7 @@
 msg.o: msg.c main.h msg.h
 client_run.o: client_run.c main.h
 mail.o: mail.c main.h
+error.o: error.c main.h msg.h
 
 clean:
 	rm -f *.o ts
--- a/client.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/client.c	Thu Apr 05 21:45:25 2007 +0200
@@ -4,7 +4,6 @@
 
     Please find the license in the provided COPYING file.
 */
-#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -37,7 +36,8 @@
 
     /* Alloc */
     commandstring = (char *) malloc(size);
-    assert(commandstring != NULL);
+    if(commandstring == NULL)
+        error("Error in malloc for commandstring");
 
     /* Build the command */
     strcpy(commandstring, array[0]);
@@ -80,11 +80,9 @@
 
     res = recv_msg(server_socket, &m);
     if(res == -1)
-    {
-        perror("read");
-        exit(-1);
-    }
-    assert(m.type = NEWJOB_OK);
+        error("Error in wait_newjob_ok");
+    if(m.type != NEWJOB_OK)
+        error("Error getting the newjob_ok");
 
     return m.u.jobid;
 }
@@ -96,21 +94,14 @@
 
     while (1)
     {
-        res = recv(server_socket, &m, sizeof(m), 0);
+        res = recv_msg(server_socket, &m);
         if(res == -1)
-        {
-            perror("read");
-            exit(-1);
-        }
+            error("Error in wait_server_commands");
 
         if (res == 0)
             break;
-        if (res != sizeof(m))
-        {
-            fprintf(stderr, "c: recv() message size wrong: %i instead of %i\n",
-                res, (int) sizeof(m));
-        }
-        assert(res == sizeof(m));
+        if(res != sizeof(m))
+            error("Error in wait_server_commands");
         if (m.type == RUNJOB)
         {
             int errorlevel;
@@ -132,14 +123,12 @@
     {
         res = recv_msg(server_socket, &m);
         if(res == -1)
-        {
-            perror("read");
-            exit(-1);
-        }
+            error("Error in wait_server_lines");
 
         if (res == 0)
             break;
-        assert(res == sizeof(m));
+        if(res != sizeof(m))
+            error("Error in wait_server_lines 2");
         if (m.type == LIST_LINE)
         {
             char * buffer;
@@ -154,13 +143,10 @@
 void c_list_jobs()
 {
     struct msg m;
-    int res;
 
     m.type = LIST;
 
-    res = send(server_socket, &m, sizeof(m), 0);
-    if(res == -1)
-        perror("send");
+    send_msg(server_socket, &m);
 }
 
 void c_send_runjob_ok(const char *ofname, int pid)
@@ -186,14 +172,11 @@
 static void c_end_of_job(int errorlevel)
 {
     struct msg m;
-    int res;
 
     m.type = ENDJOB;
     m.u.errorlevel = errorlevel;
 
-    res = send(server_socket, &m, sizeof(m),0);
-    if(res == -1)
-        perror("send");
+    send_msg(server_socket, &m);
 }
 
 void c_shutdown_server()
@@ -225,7 +208,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in get_output_file");
     switch(m.type)
     {
     case ANSWER_OUTPUT:
@@ -243,14 +227,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != m.u.line_size)
+            error("Error in get_output_file line size");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in get_output_file line size");
     }
     /* This will never be reached */
     return 0;
@@ -319,7 +303,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in remove_job");
     switch(m.type)
     {
     case REMOVEJOB_OK:
@@ -328,14 +313,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != sizeof(m))
+            error("Error in remove_job");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in remove_job");
     }
     /* This will never be reached */
 }
@@ -354,7 +339,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in wait_job");
     switch(m.type)
     {
     case WAITJOB_OK:
@@ -363,14 +349,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != m.u.line_size)
+            error("Error in wait_job - line size");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in c_wait_job");
     }
     /* This will never be reached */
     return -1;
@@ -389,7 +375,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in move_urgent");
     switch(m.type)
     {
     case URGENT_OK:
@@ -398,14 +385,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != m.u.line_size)
+            error("Error in move_urgent - line size");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in move_urgent");
     }
     /* This will never be reached */
     return;
@@ -424,7 +411,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in get_state - line size");
     switch(m.type)
     {
     case ANSWER_STATE:
@@ -434,14 +422,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != m.u.line_size)
+            error("Error in get_state - line size");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in get_state");
     }
     /* This will never be reached */
     return;
@@ -461,7 +449,8 @@
 
     /* Receive the answer */
     res = recv_msg(server_socket, &m);
-    assert(res == sizeof(m));
+    if(res != sizeof(m))
+        error("Error in swap_jobs");
     switch(m.type)
     {
     case SWAP_JOBS_OK:
@@ -470,14 +459,14 @@
     case LIST_LINE: /* Only ONE line accepted */
         string = (char *) malloc(m.u.line_size);
         res = recv_bytes(server_socket, string, m.u.line_size);
-        assert(res == m.u.line_size);
+        if(res != m.u.line_size)
+            error("Error in swap_jobs - line size");
         fprintf(stderr, "Error in the request: %s", 
                 string);
         exit(-1);
         /* WILL NOT GO FURTHER */
     default:
-        fprintf(stderr, "Wrong internal message\n");
-        exit(-1);
+        warning("Wrong internal message in swap_jobs");
     }
     /* This will never be reached */
     return;
--- a/client_run.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/client_run.c	Thu Apr 05 21:45:25 2007 +0200
@@ -7,6 +7,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <stdio.h> /* BAD. main requires this header. */
+
 #include "main.h"
 
 void c_run_tail(const char *filename)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/error.c	Thu Apr 05 21:45:25 2007 +0200
@@ -0,0 +1,128 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#include "main.h"
+#include "msg.h"
+
+/* Declared in main.h as extern */
+enum Process_type process_type;
+
+static int real_errno;
+
+/* Local protos */
+static void dump_structs(FILE *out);
+
+
+static void print_date(FILE *out)
+{
+    time_t t;
+    const char *tstr;
+
+    t = time(NULL);
+    tstr = ctime(&t);
+
+    fprintf(out, "date \"%s\"\n", tstr);
+}
+
+static void dump_proc_info(FILE *out)
+{
+    print_date(out);
+    fprintf(out, "pid %i\n", getpid());
+    if (process_type == SERVER)
+        fprintf(out, "type SERVER\n");
+    else if (process_type == CLIENT)
+        fprintf(out, "type CLIENT\n");
+    else
+        fprintf(out, "type UNKNOWN\n");
+}
+
+static FILE * open_error_file()
+{
+    int fd;
+    FILE* out;
+
+    fd = open("/tmp/ts.error", O_APPEND | O_WRONLY, 0600);
+    if (fd == -1)
+        return 0;
+
+    out = fdopen(fd, "a");
+    if (out == NULL)
+    {
+        close(fd);
+        return 0;
+    }
+
+    return out;
+}
+
+static void print_error(FILE *out, enum Etype type, const char *str, va_list ap)
+{
+    if (type == ERROR)
+        fprintf(out, "Error\n");
+    else if (type == WARNING)
+        fprintf(out, "Warning\n");
+    else
+        fprintf(out, "Unknown kind of error\n");
+
+    fprintf(out, " Msg: ");
+
+    vfprintf(out, str, ap);
+
+    fprintf(out, "\n");
+    fprintf(out, " errno %i, \"%s\"", real_errno, strerror(real_errno));
+}
+
+static void problem(enum Etype type, const char *str, va_list ap)
+{
+    FILE *out;
+
+    out = open_error_file();
+    if (out == 0)
+        return;
+
+    /* out is ready */
+    print_error(out, type, str, ap);
+    dump_structs(out);
+
+    /* this will close the fd also */
+    fclose(out);
+}
+
+void error(const char *str, ...)
+{
+    va_list ap;
+
+    va_start(ap, str);
+
+    real_errno = errno;
+
+    problem(ERROR, str, ap);
+}
+
+void warning(const char *str, ...)
+{
+    va_list ap;
+
+    va_start(ap, str);
+
+    real_errno = errno;
+
+    problem(WARNING, str, ap);
+}
+
+static void dump_structs(FILE *out)
+{
+    dump_proc_info(out);
+    if (process_type == SERVER)
+    {
+        dump_jobs_struct(out);
+        dump_conns_struct(out);
+    }
+}
--- a/execute.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/execute.c	Thu Apr 05 21:45:25 2007 +0200
@@ -7,7 +7,6 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <signal.h>
-#include <assert.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -33,14 +32,13 @@
     if (command_line.store_output) {
         res = read(fd_read_filename, &namesize, sizeof(namesize));
         if (res == -1)
-        {
-            perror("read filename");
-            exit(-1);
-        }
-        assert(res == sizeof(namesize));
+            error("read the filename from %i", fd_read_filename);
+        if (res != sizeof(namesize))
+            error("Reading the size of the name");
         ofname = (char *) malloc(namesize);
         res = read(fd_read_filename, ofname, namesize);
-        assert(res == namesize);
+        if (res != sizeof(namesize))
+            error("Reading the the out file name");
     }
     close(fd_read_filename);
 
@@ -187,12 +185,11 @@
             run_child(p[1]);
             /* Not reachable, if the 'exec' of the command
              * works. Thus, command exists, etc. */
+            fprintf(stderr, "ts could not run the command\n");
             exit(-1);
             break;
         case -1:
-            perror("Error in fork");
-            exit(-1);
-            ;
+            error("forking");
         default:
             close(p[1]);
             errorlevel = run_parent(p[0], pid);
--- a/jobs.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/jobs.c	Thu Apr 05 21:45:25 2007 +0200
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
-#include <assert.h>
 #include <string.h>
 #include "msg.h"
 #include "main.h"
@@ -264,11 +263,13 @@
     p->command = malloc(m->u.newjob.command_size);
     /* !!! Check retval */
     res = recv_bytes(s, p->command, m->u.newjob.command_size);
-    assert(res != -1);
+    if (res == -1)
+        error("wrong bytes received");
 
     return p->jobid;
 }
 
+/* This assumes the jobid exists */
 void s_removejob(int jobid)
 {
     struct Job *p;
@@ -294,7 +295,8 @@
             break;
         p = p->next;
     }
-    assert(p->next != 0);
+    if (p->next == 0)
+        error("Job to be removed not found");
 
     newnext = p->next->next;
 
@@ -374,10 +376,14 @@
 {
     struct Job *newfirst;
 
-    assert(state == WAITING);
-    assert(firstjob != 0);
+    if (state != WAITING)
+        error("Wrong state in the server. Not WAITING, but %i", state);
+    if (firstjob == 0)
+        error("on job finished, firstjob values %x", firstjob);
 
-    assert(firstjob->state == RUNNING);
+    if (firstjob->state != RUNNING)
+        error("on job finished, the firstjob is not running but %i",
+                firstjob->state);
 
     /* Mark state */
     firstjob->state = FINISHED;
@@ -419,8 +425,11 @@
 {
     struct Job *p;
     p = findjob(jobid);
-    assert(p != 0);
-    assert(p->state == RUNNING);
+    if (p == 0)
+        error("Job %i already run not found on runjob_ok", jobid);
+    if (p->state != RUNNING)
+        error("Job %i not running, but %i on runjob_ok", jobid,
+                p->state);
 
     p->pid = pid;
     p->output_filename = oname;
@@ -438,7 +447,9 @@
         if (state == WAITING)
         {
             p = firstjob;
-            assert(p != 0);
+            if (p == 0)
+                error("Internal state WAITING, but job not run."
+                        "firstjob = %x", firstjob);
         }
         else
         {
@@ -814,3 +825,39 @@
     /* Interchange the pointers */
     send_state(s, p->state);
 }
+
+static void dump_job_struct(FILE *out, const struct Job *p)
+{
+    fprintf(out, "  new_job\n");
+    fprintf(out, "    jobid %i\n", p->jobid);
+    fprintf(out, "    command \"%s\"\n", p->command);
+    fprintf(out, "    state %s\n",
+            jstate2string(p->state));
+    fprintf(out, "    errorlevel %i\n", p->errorlevel);
+    fprintf(out, "    output_filename \"%s\"\n",
+            p->output_filename ? p->output_filename : "NULL");
+    fprintf(out, "    store_output %i\n", p->store_output);
+    fprintf(out, "    pid %i\n", p->pid);
+    fprintf(out, "    should_keep_finished %i\n", p->pid);
+}
+
+void dump_jobs_struct(FILE *out)
+{
+    const struct Job *p;
+
+    fprintf(out, "New_jobs");
+
+    p = firstjob;
+    while (p != 0)
+    {
+        dump_job_struct(out, p);
+        p = p->next;
+    }
+
+    p = first_finished_job;
+    while (p != 0)
+    {
+        dump_job_struct(out, p);
+        p = p->next;
+    }
+}
--- a/mail.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/mail.c	Thu Apr 05 21:45:25 2007 +0200
@@ -5,7 +5,6 @@
     Please find the license in the provided COPYING file.
 */
 #include <signal.h>
-#include <assert.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -35,10 +34,9 @@
             close(2);
             dup2(p[0], 0);
             execl("/usr/sbin/sendmail", "sendmail", "-oi", dest, NULL);
-            exit(-1);
+            error("run sendmail");
         case -1:
-            perror("fork sendmail");
-            exit(-1);
+            error("fork sendmail");
         default: /* Parent */
             ;
     }
@@ -51,7 +49,8 @@
     FILE *f;
 
     f = fdopen(fd, "a");
-    assert(f != NULL);
+    if (f == NULL)
+        error("Cannot fdopen the letter file");
 
     fprintf(f, "From: Task Spooler <taskspooler>\n");
     fprintf(f, "To: %s\n", dest);
@@ -71,17 +70,20 @@
     int res;
 
     file_fd = open(ofname, O_RDONLY);
-    assert(file_fd != -1);
+    if (file_fd == -1)
+        error("mail: Cannot open the output file %s", ofname);
 
     do {
         read_bytes = read(file_fd, buffer, 1000);
         if (read_bytes > 0)
         {
             res = write(write_fd, buffer, read_bytes);
-            assert(res != -1);
+            if (res == -1)
+                warning("Cannot write to the mail pipe %i", write_fd);
         }
     } while (read_bytes > 0);
-    assert(read_bytes != -1);
+    if (read_bytes == -1)
+        warning("Cannot read the output file %s from %i", ofname, file_fd);
 }
 
 void hook_on_finish(int jobid, int errorlevel, const char *ofname,
@@ -106,10 +108,8 @@
             sprintf(serrorlevel, "%i", errorlevel);
             execlp(onfinish, onfinish, sjobid, serrorlevel, ofname, command,
                     NULL);
-            exit(-1);
         case -1:
-            perror("fork on finish");
-            exit(-1);
+            error("fork on finish");
         default: /* Parent */
             wait(&status);
     }
--- a/main.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/main.c	Thu Apr 05 21:45:25 2007 +0200
@@ -5,7 +5,6 @@
     Please find the license in the provided COPYING file.
 */
 #include <unistd.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -254,8 +253,7 @@
     switch(pid)
     {
         case -1:
-            perror("fork failed");
-            exit(-1);
+            error("fork failed");
             break;
         case 0:
             close(0);
@@ -346,8 +344,11 @@
         print_help(argv[0]);
         break;
     case c_QUEUE:
-        assert(command_line.command.num > 0);
-        assert(command_line.need_server);
+        if (command_line.command.num <= 0)
+            error("Tried to queue a void command. parameters: %i",
+                    command_line.command.num);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_new_job();
         command_line.jobid = c_wait_newjob_ok();
         if (command_line.store_output)
@@ -365,54 +366,66 @@
         }
         break;
     case c_LIST:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_list_jobs();
         c_wait_server_lines();
         break;
     case c_KILL_SERVER:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_shutdown_server();
         break;
     case c_CLEAR_FINISHED:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_clear_finished();
         break;
     case c_TAIL:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_tail();
         /* This will not return! */
         break;
     case c_CAT:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_cat();
         /* This will not return! */
         break;
     case c_SHOW_OUTPUT_FILE:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_show_output_file();
         break;
     case c_SHOW_PID:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_show_pid();
         break;
     case c_REMOVEJOB:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_remove_job();
         break;
     case c_WAITJOB:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         errorlevel = c_wait_job();
         break;
     case c_URGENT:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_move_urgent();
         break;
     case c_SWAP_JOBS:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         c_swap_jobs();
         break;
     case c_GET_STATE:
-        assert(command_line.need_server);
+        if (!command_line.need_server)
+            error("The command %i needs the server", command_line.request);
         /* This will also print the state into stdout */
         c_get_state();
         break;
--- a/main.h	Thu Apr 05 19:19:09 2007 +0200
+++ b/main.h	Thu Apr 05 21:45:25 2007 +0200
@@ -34,8 +34,14 @@
     } command;
 };
 
+enum Process_type {
+    CLIENT,
+    SERVER
+};
+
 extern struct Command_line command_line;
 extern int server_socket;
+extern enum Process_type process_type;
 
 struct msg;
 
@@ -76,9 +82,11 @@
 void s_move_urgent(int s, int jobid);
 void s_send_state(int s, int jobid);
 void s_swap_jobs(int s, int jobid1, int jobid2);
+void dump_jobs_struct(FILE *out);
 
 /* server.c */
 void server_main(int notify_fd, char *_path);
+void dump_conns_struct(FILE *out);
 
 /* server_start.c */
 int try_connect(int s);
@@ -98,3 +106,12 @@
     const char *command);
 void hook_on_finish(int jobid, int errorlevel, const char *ofname,
     const char *command);
+
+/* error.c */
+enum Etype
+{
+    WARNING,
+    ERROR
+};
+void error(const char *str, ...);
+void warning(const char *str, ...);
--- a/msg.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/msg.c	Thu Apr 05 21:45:25 2007 +0200
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "msg.h"
+#include "main.h"
 
 void send_bytes(const int fd, const char *data, const int bytes)
 {
@@ -16,10 +17,7 @@
     /* Send the message */
     res = send(fd, data, bytes, 0);
     if(res == -1)
-    {
-        perror("c: send");
-        exit(-1);
-    }
+        warning("Sending %i bytes to %i.", bytes, fd);
 }
 
 int recv_bytes(const int fd, char *data, const int bytes)
@@ -27,6 +25,8 @@
     int res;
     /* Send the message */
     res = recv(fd, data, bytes, 0);
+    if(res == -1)
+        warning("Receiving %i bytes from %i.", bytes, fd);
 
     return res;
 }
@@ -38,10 +38,7 @@
     msgdump(m);
     res = send(fd, m, sizeof(*m), 0);
     if(res == -1)
-    {
-        perror("c: send");
-        exit(-1);
-    }
+        warning("Sending a message to %i.", fd);
 }
 
 int recv_msg(const int fd, struct msg *m)
@@ -49,6 +46,8 @@
     int res;
     /* Send the message */
     res = recv(fd, m, sizeof(*m), 0);
+    if(res == -1)
+        warning("Receiving a message from %i.", fd);
     if (res == sizeof(*m))
         msgdump(m);
 
--- a/msgdump.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/msgdump.c	Thu Apr 05 21:45:25 2007 +0200
@@ -16,7 +16,7 @@
     switch(m->type)
     {
         case KILL_SERVER:
-            printf("  KILL SERVER\n");
+            printf(" KILL SERVER\n");
             break;
         case NEWJOB:
             printf(" NEWJOB\n");
@@ -54,6 +54,6 @@
             printf(" PID: %i\n", m->u.output.pid);
             break;
         default:
-            printf(" Unknown message\n");
+            printf(" Unknown message: %i\n", m->type);
     }
 }
--- a/server.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/server.c	Thu Apr 05 21:45:25 2007 +0200
@@ -4,7 +4,6 @@
 
     Please find the license in the provided COPYING file.
 */
-#include <assert.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -61,24 +60,19 @@
     nconnections = 0;
 
     ls = socket(PF_UNIX, SOCK_STREAM, 0);
-    assert(ls != -1);
+    if(ls == -1)
+        error("cannot create the listen socket in the server");
 
     addr.sun_family = AF_UNIX;
     strcpy(addr.sun_path, path);
 
     res = bind(ls, (struct sockaddr *) &addr, sizeof(addr));
     if (res == -1)
-    {
-        perror("Error binding.");
-        return;
-    }
+        error("Error binding.");
 
     res = listen(ls, 0);
     if (res == -1)
-    {
-        perror("Error listening.");
-        return;
-    }
+        error("Error listening.");
 
     notify_parent(notify_fd);
 
@@ -118,7 +112,8 @@
         {
             int cs;
             cs = accept(ls, NULL, NULL);
-            assert(cs != -1);
+            if (cs == -1)
+                error("Accepting from %i", ls);
             client_cs[nconnections++].socket = cs;
         }
         for(i=0; i< nconnections; ++i)
@@ -181,13 +176,15 @@
     s = client_cs[index].socket;
 
     /* Read the message */
-    res = recv(s, &m, sizeof(m),0);
+    res = recv_msg(s, &m);
     if (res == -1)
     {
-        fprintf(stderr, "Error reading from client %i, socket %i\n",
-                index, s);
-        perror("client read");
-        exit(-1);
+        warning("client read");
+        close(s);
+        remove_connection(index);
+        /* It will not fail, even if the index is not a notification */
+        s_remove_notification(index);
+        return NOBREAK;
     }
     if (res == 0)
     {
@@ -220,7 +217,8 @@
             buffer = (char *) malloc(m.u.output.ofilename_size);
             res = recv_bytes(client_cs[index].socket, buffer,
                 m.u.output.ofilename_size);
-            assert(res == m.u.output.ofilename_size);
+            if (res != m.u.output.ofilename_size)
+                error("Reading the ofilename");
         }
         s_process_runjob_ok(client_cs[index].jobid, buffer,
                 m.u.output.pid);
@@ -283,33 +281,49 @@
 {
     int s;
     struct msg m;
-    int res;
     
-    assert(client_cs[index].hasjob);
+    if (!client_cs[index].hasjob)
+        error("Run job of the client %i which doesn't have any job", index);
 
     s = client_cs[index].socket;
 
     m.type = RUNJOB;
 
-    res = send(s, &m, sizeof(m), 0);
-    if(res == -1)
-        perror("send");
+    send_msg(s, &m);
 }
 
 static void s_newjob_ok(int index)
 {
     int s;
     struct msg m;
-    int res;
     
-    assert(client_cs[index].hasjob);
+    if (!client_cs[index].hasjob)
+        error("Run job of the client %i which doesn't have any job", index);
 
     s = client_cs[index].socket;
 
     m.type = NEWJOB_OK;
     m.u.jobid = client_cs[index].jobid;
 
-    res = send(s, &m, sizeof(m), 0);
-    if(res == -1)
-        perror("send");
+    send_msg(s, &m);
+}
+
+static void dump_conn_struct(FILE *out, const struct Client_conn *p)
+{
+    fprintf(out, "  new_conn\n");
+    fprintf(out, "    socket %i\n", p->socket);
+    fprintf(out, "    hasjob \"%i\"\n", p->hasjob);
+    fprintf(out, "    jobid %i\n", p->jobid);
 }
+
+void dump_conns_struct(FILE *out)
+{
+    int i;
+
+    fprintf(out, "New_conns");
+
+    for(i=0; i < nconnections; ++i)
+    {
+        dump_conn_struct(out, &client_cs[i]);
+    }
+}
--- a/server_start.c	Thu Apr 05 19:19:09 2007 +0200
+++ b/server_start.c	Thu Apr 05 21:45:25 2007 +0200
@@ -5,7 +5,6 @@
     Please find the license in the provided COPYING file.
 */
 #include <unistd.h>
-#include <assert.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -124,7 +123,8 @@
     int notify_fd;
 
     server_socket = socket(PF_UNIX, SOCK_STREAM, 0);
-    assert(server_socket != -1);
+    if (server_socket == -1)
+        error("getting the server socket");
 
     create_path();
 
@@ -136,10 +136,7 @@
 
     /* If error other than "No one listens on the other end"... */
     if (!(errno == ENOENT || errno == ECONNREFUSED))
-    {
-        perror("c: cannot connect to the server");
-        exit(-1);
-    }
+        error("c: cannot connect to the server");
 
     if (errno == ECONNREFUSED)
         unlink(path);
--- a/ts.1	Thu Apr 05 19:19:09 2007 +0200
+++ b/ts.1	Thu Apr 05 21:45:25 2007 +0200
@@ -179,11 +179,10 @@
 Also, remember that stdin/stdout/stderr will be detached, so
 don't use your shell's redirection operators when you put a job into background.
 
-The
-.B ts
-processes don't die very well. Take care not killing any of them, because they
-can bring the queue server down. It should be fixed in newer releases of this
-software.
+Now, if an internal problem is found in runtime, a file
+.B /tmp/ts.error
+is created, which you can submit to the developer in order to fix the bug.
+
 .SH SEE ALSO
 .BR at (1)
 .SH AUTHOR