server and server-modules with mallok(), reallok(), and phree().
Wrote macros and a set of leak-tracking functions.
+Tue Jan 5 23:24:52 EST 1999 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
+ * 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 <ajc@uncnsrd.mt-kisco.ny.us>
* Documentation changes
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);
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) {
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);
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",
for (a=0; a<MAXKEYS; ++a) {
if (dtkey[a].dptr != NULL) {
- free(dtkey[a].dptr);
+ phree(dtkey[a].dptr);
}
}
return NULL;
}
- tempcdb = (struct cdbdata *) malloc(sizeof(struct cdbdata));
+ tempcdb = (struct cdbdata *) mallok(sizeof(struct cdbdata));
if (tempcdb == NULL) {
lprintf(2, "Cannot allocate memory!\n");
}
* more complex stuff with other database managers in the future).
*/
void cdb_free(struct cdbdata *cdb) {
- free(cdb->ptr);
- free(cdb);
+ phree(cdb->ptr);
+ phree(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);
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;
void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc)
{
- struct ProtoFunctionHook *p = malloc(sizeof *p);
+ struct ProtoFunctionHook *p = mallok(sizeof *p);
if (p == NULL)
{
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;
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;
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;
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;
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],
end_critical_section(S_MSGMAIN);
if (generate_id) {
- free(actual_message);
+ phree(actual_message);
}
/* Finally, return the pointers */
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;
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);
struct cdbdata *cdbfr;
if (CC->msglist != NULL) {
- free(CC->msglist);
+ phree(CC->msglist);
}
CC->msglist = NULL;
CC->num_msgs = 0;
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);
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);
/* Now add the new message */
++num_msgs;
- msglist = realloc(msglist,
+ msglist = reallok(msglist,
(num_msgs * sizeof(long)) );
if (msglist == NULL) {
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);
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",
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);
}
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");
|| (!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" ),
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;
delete_room(&qrbuf);
}
pptr = RoomPurgeList->next;
- free(RoomPurgeList);
+ phree(RoomPurgeList);
RoomPurgeList = pptr;
++num_rooms_purged;
}
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;
while (UserPurgeList != NULL) {
purge_user(UserPurgeList->name);
pptr = UserPurgeList->next;
- free(UserPurgeList);
+ phree(UserPurgeList);
UserPurgeList = pptr;
++num_users_purged;
}
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;
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;
/* 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;
/* 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;
}
VisitPurgeList->vp_usernum);
cdb_delete(CDB_VISIT, IndexBuf, IndexLen);
vptr = VisitPurgeList->next;
- free(VisitPurgeList);
+ phree(VisitPurgeList);
VisitPurgeList = vptr;
++purged;
}
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");
fread(msgtext, msglen, 1, imfp);
cdb_store(CDB_MSGMAIN, &msgnum, sizeof(long), msgtext, msglen);
- free(msgtext);
+ phree(msgtext);
}
void imp_floors(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;
}
CC->num_msgs = num_msgs;
put_msglist(&qr);
}
- free(msglist);
+ phree(msglist);
}
}
/* $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;
#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
#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() */
}
+
+#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...
*/
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);
}
lprintf(9, "Freeing session context...\n");
- free(con);
+ phree(con);
lprintf(9, "...done.\n");
end_critical_section(S_SESSION_TABLE);
Important items
---------------
* In the client, make <G>oto go directly to Mail> when there's new mail.
+* Implement multi-line pages.
Honeydew items
--------------