From 0e27f6b5504c48cf1f2c9d4ffa0a213523aa3966 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 6 Jan 1999 04:26:06 +0000 Subject: [PATCH] * Replaced all occurances of malloc(), realloc(), and free() in the server and server-modules with mallok(), reallok(), and phree(). Wrote macros and a set of leak-tracking functions. --- citadel/ChangeLog | 5 +++ citadel/citserver.c | 26 +++++++++------ citadel/database.c | 14 ++++---- citadel/dynloader.c | 10 +++--- citadel/msgbase.c | 8 ++--- citadel/room_ops.c | 10 +++--- citadel/serv_chat.c | 8 ++--- citadel/serv_expire.c | 20 +++++------ citadel/serv_upgrade.c | 8 ++--- citadel/server.h | 35 +++++++++++++++++++ citadel/sysdep.c | 76 ++++++++++++++++++++++++++++++++++++++++-- citadel/tasklist.txt | 1 + 12 files changed, 170 insertions(+), 51 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 77a151672..1c018fab2 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,3 +1,8 @@ +Tue Jan 5 23:24:52 EST 1999 Art Cancro + * Replaced all occurances of malloc(), realloc(), and free() in the + server and server-modules with mallok(), reallok(), and phree(). + Wrote macros and a set of leak-tracking functions. + Sun Jan 3 20:38:45 EST 1999 Art Cancro * Documentation changes diff --git a/citadel/citserver.c b/citadel/citserver.c index a2aecf591..1ab8a0f58 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -111,12 +111,12 @@ void cleanup_stuff(void *arg) while (CC->FirstExpressMessage != NULL) { emptr = CC->FirstExpressMessage; CC->FirstExpressMessage = CC->FirstExpressMessage->next; - free(emptr); + phree(emptr); } end_critical_section(S_SESSION_TABLE); /* Deallocate any message list we might have in memory */ - if (CC->msglist != NULL) free(CC->msglist); + if (CC->msglist != NULL) phree(CC->msglist); /* Now get rid of the session and context */ lprintf(7, "cleanup_stuff() calling RemoveContext(%d)\n", CC->cs_pid); @@ -377,13 +377,13 @@ void cmd_mesg(char *mname) extract(buf,mname,0); - dirs[0]=malloc(64); - dirs[1]=malloc(64); + dirs[0]=mallok(64); + dirs[1]=mallok(64); strcpy(dirs[0],"messages"); strcpy(dirs[1],"help"); mesg_locate(targ,buf,2,dirs); - free(dirs[0]); - free(dirs[1]); + phree(dirs[0]); + phree(dirs[1]); if (strlen(targ)==0) { @@ -432,13 +432,13 @@ void cmd_emsg(char *mname) if (buf[a] == '/') buf[a] = '.'; } - dirs[0]=malloc(64); - dirs[1]=malloc(64); + dirs[0]=mallok(64); + dirs[1]=mallok(64); strcpy(dirs[0],"messages"); strcpy(dirs[1],"help"); mesg_locate(targ,buf,2,dirs); - free(dirs[0]); - free(dirs[1]); + phree(dirs[0]); + phree(dirs[1]); if (strlen(targ)==0) { snprintf(targ, sizeof targ, "./help/%s", buf); @@ -1101,6 +1101,12 @@ void *context_loop(struct CitContext *con) cmd_conf(&cmdbuf[5]); } +#ifdef DEBUG_MEMORY_LEAKS + else if (!strncasecmp(cmdbuf, "LEAK", 4)) { + dump_tracked(); + } +#endif + else if (!DLoader_Exec_Cmd(cmdbuf)) { cprintf("%d Unrecognized or unsupported command.\n", diff --git a/citadel/database.c b/citadel/database.c index aea8961b3..e67c6d373 100644 --- a/citadel/database.c +++ b/citadel/database.c @@ -169,7 +169,7 @@ void close_databases(void) { for (a=0; aptr); - free(cdb); + phree(cdb->ptr); + phree(cdb); } @@ -275,7 +275,7 @@ void cdb_free(struct cdbdata *cdb) { void cdb_rewind(int cdb) { if (dtkey[CC->cs_pid].dptr != NULL) { - free(dtkey[CC->cs_pid].dptr); + phree(dtkey[CC->cs_pid].dptr); } begin_critical_section(S_DATABASE); @@ -301,11 +301,11 @@ struct cdbdata *cdb_next_item(int cdb) { dret = gdbm_fetch(gdbms[cdb], dtkey[CC->cs_pid]); end_critical_section(S_DATABASE); if (dret.dptr == NULL) { /* bad read */ - free(dtkey[CC->cs_pid].dptr); + phree(dtkey[CC->cs_pid].dptr); return NULL; } - cdbret = (struct cdbdata *) malloc(sizeof(struct cdbdata)); + cdbret = (struct cdbdata *) mallok(sizeof(struct cdbdata)); cdbret->len = dret.dsize; cdbret->ptr = dret.dptr; diff --git a/citadel/dynloader.c b/citadel/dynloader.c index 6d452763d..e860fba37 100644 --- a/citadel/dynloader.c +++ b/citadel/dynloader.c @@ -43,7 +43,7 @@ struct ProtoFunctionHook void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc) { - struct ProtoFunctionHook *p = malloc(sizeof *p); + struct ProtoFunctionHook *p = mallok(sizeof *p); if (p == NULL) { @@ -127,7 +127,7 @@ void CtdlRegisterLogHook(void (*fcn_ptr)(char *), int loglevel) { struct LogFunctionHook *newfcn; newfcn = (struct LogFunctionHook *) - malloc(sizeof(struct LogFunctionHook)); + mallok(sizeof(struct LogFunctionHook)); newfcn->next = LogHookTable; newfcn->h_function_pointer = fcn_ptr; newfcn->loglevel = loglevel; @@ -142,7 +142,7 @@ void CtdlRegisterCleanupHook(void (*fcn_ptr)(void)) { struct CleanupFunctionHook *newfcn; newfcn = (struct CleanupFunctionHook *) - malloc(sizeof(struct CleanupFunctionHook)); + mallok(sizeof(struct CleanupFunctionHook)); newfcn->next = CleanupHookTable; newfcn->h_function_pointer = fcn_ptr; CleanupHookTable = newfcn; @@ -156,7 +156,7 @@ void CtdlRegisterSessionHook(void (*fcn_ptr)(void), int EventType) { struct SessionFunctionHook *newfcn; newfcn = (struct SessionFunctionHook *) - malloc(sizeof(struct SessionFunctionHook)); + mallok(sizeof(struct SessionFunctionHook)); newfcn->next = SessionHookTable; newfcn->h_function_pointer = fcn_ptr; newfcn->eventtype = EventType; @@ -172,7 +172,7 @@ void CtdlRegisterUserHook(void (*fcn_ptr)(char*, long), int EventType) { struct UserFunctionHook *newfcn; newfcn = (struct UserFunctionHook *) - malloc(sizeof(struct UserFunctionHook)); + mallok(sizeof(struct UserFunctionHook)); newfcn->next = UserHookTable; newfcn->h_function_pointer = fcn_ptr; newfcn->eventtype = EventType; diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 51fbc20d4..e76c6d3d9 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -663,7 +663,7 @@ long send_message(char *message_in_memory, /* pointer to buffer */ if (generate_id) { sprintf(msgidbuf, "I%ld", newmsgid); actual_length = message_length + strlen(msgidbuf) + 1; - actual_message = malloc(actual_length); + actual_message = mallok(actual_length); memcpy(actual_message, message_in_memory, 3); memcpy(&actual_message[3], msgidbuf, (strlen(msgidbuf)+1) ); memcpy(&actual_message[strlen(msgidbuf)+4], @@ -688,7 +688,7 @@ long send_message(char *message_in_memory, /* pointer to buffer */ end_critical_section(S_MSGMAIN); if (generate_id) { - free(actual_message); + phree(actual_message); } /* Finally, return the pointers */ @@ -758,7 +758,7 @@ void save_message(char *mtmp, /* file containing proper message */ templen = statbuf.st_size; /* Now read it into memory */ - message_in_memory = (char *) malloc(templen); + message_in_memory = (char *) mallok(templen); if (message_in_memory == NULL) { lprintf(2, "Can't allocate memory to save message!\n"); return; @@ -769,7 +769,7 @@ void save_message(char *mtmp, /* file containing proper message */ fclose(fp); newmsgid = send_message(message_in_memory, templen, generate_id); - free(message_in_memory); + phree(message_in_memory); if (newmsgid <= 0L) return; strcpy(actual_rm, CC->quickroom.QRname); diff --git a/citadel/room_ops.c b/citadel/room_ops.c index 2bdd6ed30..7c9ee502c 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -287,7 +287,7 @@ void get_msglist(struct quickroom *whichroom) { struct cdbdata *cdbfr; if (CC->msglist != NULL) { - free(CC->msglist); + phree(CC->msglist); } CC->msglist = NULL; CC->num_msgs = 0; @@ -297,7 +297,7 @@ void get_msglist(struct quickroom *whichroom) { return; } - CC->msglist = malloc(cdbfr->len); + CC->msglist = mallok(cdbfr->len); memcpy(CC->msglist, cdbfr->ptr, cdbfr->len); CC->num_msgs = cdbfr->len / sizeof(long); cdb_free(cdbfr); @@ -349,7 +349,7 @@ long AddMessageToRoom(struct quickroom *whichroom, long newmsgid) { num_msgs = 0; } else { - msglist = malloc(cdbfr->len); + msglist = mallok(cdbfr->len); num_msgs = cdbfr->len / sizeof(long); memcpy(msglist, cdbfr->ptr, cdbfr->len); cdb_free(cdbfr); @@ -357,7 +357,7 @@ long AddMessageToRoom(struct quickroom *whichroom, long newmsgid) { /* Now add the new message */ ++num_msgs; - msglist = realloc(msglist, + msglist = reallok(msglist, (num_msgs * sizeof(long)) ); if (msglist == NULL) { @@ -1173,7 +1173,7 @@ void delete_room(struct quickroom *qrbuf) { cdb_delete(CDB_MSGMAIN, &MsgToDelete, sizeof(long)); } put_msglist(qrbuf); - free(CC->msglist); + phree(CC->msglist); CC->msglist = NULL; CC->num_msgs = 0; delete_msglist(qrbuf); diff --git a/citadel/serv_chat.c b/citadel/serv_chat.c index 1e8dd93e3..fcacf1fd5 100644 --- a/citadel/serv_chat.c +++ b/citadel/serv_chat.c @@ -87,7 +87,7 @@ void allwrite(char *cmdbuf, int flag, char *roomname, char *username) fclose(fp); } - clnew = (struct ChatLine *) malloc(sizeof(struct ChatLine)); + clnew = (struct ChatLine *) mallok(sizeof(struct ChatLine)); memset(clnew, 0, sizeof(struct ChatLine)); if (clnew == NULL) { fprintf(stderr, "citserver: cannot alloc chat line: %s\n", @@ -130,7 +130,7 @@ void allwrite(char *cmdbuf, int flag, char *roomname, char *username) if ( (now - ChatQueue->chat_time) < 120L ) goto DONE_FREEING; clptr = ChatQueue; ChatQueue = ChatQueue->next; - free(clptr); + phree(clptr); } DONE_FREEING: end_critical_section(S_CHATQUEUE); } @@ -378,7 +378,7 @@ void cmd_pexp(char *argbuf) /* arg unused */ { begin_critical_section(S_SESSION_TABLE); emptr = CC->FirstExpressMessage; CC->FirstExpressMessage = CC->FirstExpressMessage->next; - free(emptr); + phree(emptr); end_critical_section(S_SESSION_TABLE); } cprintf("000\n"); @@ -446,7 +446,7 @@ void cmd_sexp(char *argbuf) || (!strcasecmp(x_user, "broadcast")) ) { strcpy(ccptr->last_pager, CC->curr_user); emnew = (struct ExpressMessage *) - malloc(sizeof(struct ExpressMessage)); + mallok(sizeof(struct ExpressMessage)); emnew->next = NULL; sprintf(emnew->em_text, "%s from %s:\n %s\n", ( (!strcasecmp(x_user, "broadcast")) ? "Broadcast message" : "Message" ), diff --git a/citadel/serv_expire.c b/citadel/serv_expire.c index 271dbf2e9..c2d34b64c 100644 --- a/citadel/serv_expire.c +++ b/citadel/serv_expire.c @@ -197,7 +197,7 @@ void DoPurgeRooms(struct quickroom *qrbuf) { if (age > purge_secs) { - pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList)); + pptr = (struct PurgeList *) mallok(sizeof(struct PurgeList)); pptr->next = RoomPurgeList; strcpy(pptr->name, qrbuf->QRname); RoomPurgeList = pptr; @@ -221,7 +221,7 @@ int PurgeRooms(void) { delete_room(&qrbuf); } pptr = RoomPurgeList->next; - free(RoomPurgeList); + phree(RoomPurgeList); RoomPurgeList = pptr; ++num_rooms_purged; } @@ -275,7 +275,7 @@ void do_user_purge(struct usersupp *us) { if (us->timescalled == 0) purge = 1; if (purge == 1) { - pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList)); + pptr = (struct PurgeList *) mallok(sizeof(struct PurgeList)); pptr->next = UserPurgeList; strcpy(pptr->name, us->fullname); UserPurgeList = pptr; @@ -297,7 +297,7 @@ int PurgeUsers(void) { while (UserPurgeList != NULL) { purge_user(UserPurgeList->name); pptr = UserPurgeList->next; - free(UserPurgeList); + phree(UserPurgeList); UserPurgeList = pptr; ++num_users_purged; } @@ -309,7 +309,7 @@ int PurgeUsers(void) { void AddValidUser(struct usersupp *usbuf) { struct ValidUser *vuptr; - vuptr = (struct ValidUser *)malloc(sizeof(struct ValidUser)); + vuptr = (struct ValidUser *)mallok(sizeof(struct ValidUser)); vuptr->next = ValidUserList; vuptr->vu_usernum = usbuf->usernum; ValidUserList = vuptr; @@ -318,7 +318,7 @@ void AddValidUser(struct usersupp *usbuf) { void AddValidRoom(struct quickroom *qrbuf) { struct ValidRoom *vrptr; - vrptr = (struct ValidRoom *)malloc(sizeof(struct ValidRoom)); + vrptr = (struct ValidRoom *)mallok(sizeof(struct ValidRoom)); vrptr->next = ValidRoomList; vrptr->vr_roomnum = qrbuf->QRnumber; vrptr->vr_roomgen = qrbuf->QRgen; @@ -384,7 +384,7 @@ int PurgeVisits(void) { /* Put the record on the purge list if it's dead */ if ((RoomIsValid==0) || (UserIsValid==0)) { vptr = (struct VPurgeList *) - malloc(sizeof(struct VPurgeList)); + mallok(sizeof(struct VPurgeList)); vptr->next = VisitPurgeList; vptr->vp_roomnum = vbuf.v_roomnum; vptr->vp_roomgen = vbuf.v_roomgen; @@ -397,14 +397,14 @@ int PurgeVisits(void) { /* Free the valid room/gen combination list */ while (ValidRoomList != NULL) { vrptr = ValidRoomList->next; - free(ValidRoomList); + phree(ValidRoomList); ValidRoomList = vrptr; } /* Free the valid user list */ while (ValidUserList != NULL) { vuptr = ValidUserList->next; - free(ValidUserList); + phree(ValidUserList); ValidUserList = vuptr; } @@ -416,7 +416,7 @@ int PurgeVisits(void) { VisitPurgeList->vp_usernum); cdb_delete(CDB_VISIT, IndexBuf, IndexLen); vptr = VisitPurgeList->next; - free(VisitPurgeList); + phree(VisitPurgeList); VisitPurgeList = vptr; ++purged; } diff --git a/citadel/serv_upgrade.c b/citadel/serv_upgrade.c index ffa6a51e5..6c49d5bb3 100644 --- a/citadel/serv_upgrade.c +++ b/citadel/serv_upgrade.c @@ -73,7 +73,7 @@ void fpgetfield(FILE *fp, char *string) void import_message(long msgnum, long msglen) { char *msgtext; - msgtext = malloc(msglen); + msgtext = mallok(msglen); if (msgtext == NULL) { lprintf(3, "ERROR: cannot allocate memory\n"); lprintf(3, "Your data files are now corrupt.\n"); @@ -83,7 +83,7 @@ void import_message(long msgnum, long msglen) { fread(msgtext, msglen, 1, imfp); cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), msgtext, msglen); - free(msgtext); + phree(msgtext); } void imp_floors(void) { @@ -188,7 +188,7 @@ void imp_rooms(void) { msglen = atol(tval); import_message(msgnum, msglen); ++num_msgs; - msglist = realloc(msglist, + msglist = reallok(msglist, (sizeof(long)*num_msgs) ); msglist[num_msgs - 1] = msgnum; } @@ -206,7 +206,7 @@ void imp_rooms(void) { CC->num_msgs = num_msgs; put_msglist(&qr); } - free(msglist); + phree(msglist); } } diff --git a/citadel/server.h b/citadel/server.h index d727f018e..89505dcd2 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -1,6 +1,10 @@ /* $Id$ */ typedef pthread_t THREAD; +/* Uncomment this if you want to track memory leaks. + * (Don't do this unless you're a developer!) + */ +#define DEBUG_MEMORY_LEAKS struct ExpressMessage { struct ExpressMessage *next; @@ -208,3 +212,34 @@ struct visit { #define UA_GOTOALLOWED 4 #define UA_HASNEWMSGS 8 #define UA_ZAPPED 16 + + + +/* Built-in debuggable stuff for checking for memory leaks */ +#ifdef DEBUG_MEMORY_LEAKS + +#define mallok(howbig) tracked_malloc(howbig, __FILE__, __LINE__) +#define phree(whichptr) tracked_free(whichptr) +#define reallok(whichptr,howbig) tracked_realloc(whichptr,howbig) + +void *tracked_malloc(size_t, char *, int); +void tracked_free(void *); +void *tracked_realloc(void *, size_t); +void dump_tracked(void); + +struct TheHeap { + struct TheHeap *next; + char h_file[32]; + int h_line; + void *h_ptr; + }; + +extern struct TheHeap *heap; + +#else + +#define mallok(howbig) malloc(howbig) +#define phree(whichptr) free(whichptr) +#define reallok(whichptr,howbig) realloc(whichptr,howbig) + +#endif diff --git a/citadel/sysdep.c b/citadel/sysdep.c index 02a5f826d..d43ffc25d 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -52,6 +52,10 @@ #include "snprintf.h" #endif +#ifdef DEBUG_MEMORY_LEAKS +struct TheHeap *heap = NULL; +#endif + pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */ pthread_key_t MyConKey; /* TSD key for MyContext() */ @@ -81,6 +85,74 @@ void lprintf(int loglevel, const char *format, ...) { } + +#ifdef DEBUG_MEMORY_LEAKS +void *tracked_malloc(size_t tsize, char *tfile, int tline) { + void *ptr; + struct TheHeap *hptr; + + ptr = malloc(tsize); + if (ptr == NULL) return(NULL); + + hptr = (struct TheHeap *) malloc(sizeof(struct TheHeap)); + strcpy(hptr->h_file, tfile); + hptr->h_line = tline; + hptr->next = heap; + hptr->h_ptr = ptr; + heap = hptr; + return ptr; + } + + +void tracked_free(void *ptr) { + struct TheHeap *hptr, *freeme; + + if (heap->h_ptr == ptr) { + hptr = heap->next; + free(heap); + heap = hptr; + } + else { + for (hptr=heap; hptr->next!=NULL; hptr=hptr->next) { + if (hptr->next->h_ptr == ptr) { + freeme = hptr->next; + hptr->next = hptr->next->next; + free(freeme); + } + } + } + + free(ptr); + } + +void *tracked_realloc(void *ptr, size_t size) { + void *newptr; + struct TheHeap *hptr; + + newptr = realloc(ptr, size); + + for (hptr=heap; hptr!=NULL; hptr=hptr->next) { + if (hptr->h_ptr == ptr) hptr->h_ptr = newptr; + } + + return newptr; + } + + +void dump_tracked() { + struct TheHeap *hptr; + + cprintf("%d Here's what's allocated...\n", LISTING_FOLLOWS); + for (hptr=heap; hptr!=NULL; hptr=hptr->next) { + cprintf("%20s %5d\n", + hptr->h_file, hptr->h_line); + } + cprintf("000\n"); + } +#endif + + + /* * Some initialization stuff... */ @@ -238,7 +310,7 @@ struct CitContext *CreateNewContext(void) { struct CitContext *me; lprintf(9, "CreateNewContext: calling malloc()\n"); - me = (struct CitContext *) malloc(sizeof(struct CitContext)); + me = (struct CitContext *) mallok(sizeof(struct CitContext)); if (me == NULL) { lprintf(1, "citserver: can't allocate memory!!\n"); pthread_exit(NULL); @@ -304,7 +376,7 @@ void RemoveContext(struct CitContext *con) } lprintf(9, "Freeing session context...\n"); - free(con); + phree(con); lprintf(9, "...done.\n"); end_critical_section(S_SESSION_TABLE); diff --git a/citadel/tasklist.txt b/citadel/tasklist.txt index 61804edad..a10f3e101 100644 --- a/citadel/tasklist.txt +++ b/citadel/tasklist.txt @@ -5,6 +5,7 @@ Priority items Important items --------------- * In the client, make oto go directly to Mail> when there's new mail. +* Implement multi-line pages. Honeydew items -------------- -- 2.39.2