]> code.citadel.org Git - citadel.git/blobdiff - citadel/serv_network.c
* if the message is not valid, try to free the message pointer in message_free
[citadel.git] / citadel / serv_network.c
index 01220281a1eb2b6ba721f2dd6d3b04f3515b498a..fb18445ed23c0e575454542ff0dfbfb78bd556de 100644 (file)
@@ -77,8 +77,7 @@ static int doing_queue = 0;
 /*
  * When we do network processing, it's accomplished in two passes; one to
  * gather a list of rooms and one to actually do them.  It's ok that rplist
- * is global; this process *only* runs as part of the housekeeping loop and
- * therefore only one will run at a time.
+ * is global; we have a mutex that keeps it safe.
  */
 struct RoomProcList *rplist = NULL;
 
@@ -426,12 +425,12 @@ void cmd_snet(char *argbuf) {
 void network_deliver_digest(struct SpoolControl *sc) {
        char buf[SIZ];
        int i;
-       struct CtdlMessage *msg;
+       struct CtdlMessage *msg = NULL;
        long msglen;
        long msgnum;
        char *instr = NULL;
        size_t instr_len = SIZ;
-       struct CtdlMessage *imsg;
+       struct CtdlMessage *imsg = NULL;
        struct namelist *nptr;
 
        if (sc->num_msgs_spooled < 1) {
@@ -531,7 +530,7 @@ void network_deliver_list(struct CtdlMessage *msg, struct SpoolControl *sc) {
        long msgnum;
        char *instr = NULL;
        size_t instr_len = SIZ;
-       struct CtdlMessage *imsg;
+       struct CtdlMessage *imsg = NULL;
        struct namelist *nptr;
 
        /* Don't do this if there were no recipients! */
@@ -865,7 +864,7 @@ void network_spool_msg(long msgnum, void *userdata) {
 
        /* Delete this message if delete-after-send is set */
        if (delete_after_send) {
-               CtdlDeleteMessages(CC->room.QRname, msgnum, "", 0);
+               CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "");
        }
 
 }
@@ -890,6 +889,11 @@ void network_spoolout_room(char *room_to_spool) {
        int skipthisline = 0;
        int i;
 
+       /*
+        * If the room doesn't exist, don't try to perform its networking tasks.
+        * Normally this should never happen, but once in a while maybe a room gets
+        * queued for networking and then deleted before it can happen.
+        */
        if (getroom(&CC->room, room_to_spool) != 0) {
                lprintf(CTDL_CRIT, "ERROR: cannot load <%s>\n", room_to_spool);
                return;
@@ -900,6 +904,7 @@ void network_spoolout_room(char *room_to_spool) {
 
        begin_critical_section(S_NETCONFIGS);
 
+       /* Only do net processing for rooms that have netconfigs */
        fp = fopen(filename, "r");
        if (fp == NULL) {
                end_critical_section(S_NETCONFIGS);
@@ -992,7 +997,7 @@ void network_spoolout_room(char *room_to_spool) {
        }
 
        /* Do something useful */
-       CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL,
+       CtdlForEachMessage(MSGS_GT, sc.lastsent, NULL, NULL, NULL,
                network_spool_msg, &sc);
 
        /* If we wrote a digest, deliver it and then close it */
@@ -1127,7 +1132,7 @@ int network_sync_to(char *target_node) {
        if (!found_node) return(-1);
 
        /* Send ALL messages */
-       num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL,
+       num_spooled = CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL,
                network_spool_msg, &sc);
 
        /* Concise cleanup because we know there's only one node in the sc */
@@ -1171,8 +1176,10 @@ void network_queue_room(struct ctdlroom *qrbuf, void *data) {
        if (ptr == NULL) return;
 
        safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
+       begin_critical_section(S_RPLIST);
        ptr->next = rplist;
        rplist = ptr;
+       end_critical_section(S_RPLIST);
 }
 
 
@@ -1321,7 +1328,7 @@ void network_bounce(struct CtdlMessage *msg, char *reason) {
  * from the inbound queue 
  */
 void network_process_buffer(char *buffer, long size) {
-       struct CtdlMessage *msg;
+       struct CtdlMessage *msg = NULL;
        long pos;
        int field;
        struct recptypes *recp = NULL;
@@ -1949,13 +1956,31 @@ void network_do_queue(void) {
        if (full_processing) {
                lprintf(CTDL_DEBUG, "network: loading outbound queue\n");
                ForEachRoom(network_queue_room, NULL);
+       }
 
+       if (rplist != NULL) {
                lprintf(CTDL_DEBUG, "network: running outbound queue\n");
                while (rplist != NULL) {
-                       network_spoolout_room(rplist->name);
+                       char spoolroomname[ROOMNAMELEN];
+                       safestrncpy(spoolroomname, rplist->name, sizeof spoolroomname);
+                       begin_critical_section(S_RPLIST);
+
+                       /* pop this record off the list */
                        ptr = rplist;
                        rplist = rplist->next;
                        free(ptr);
+
+                       /* invalidate any duplicate entries to prevent double processing */
+                       for (ptr=rplist; ptr!=NULL; ptr=ptr->next) {
+                               if (!strcasecmp(ptr->name, spoolroomname)) {
+                                       ptr->name[0] = 0;
+                               }
+                       }
+
+                       end_critical_section(S_RPLIST);
+                       if (spoolroomname[0] != 0) {
+                               network_spoolout_room(spoolroomname);
+                       }
                }
        }