K
Kieran Simkin
Hi,
I wonder if anyone can help me, I've been headscratching for a few hours
over this.
Basically, I've defined a struct called cache_object:
struct cache_object {
char hostname[HOSTSIZE+1];
char ipaddr[IPSIZE+1];
};
I plan to store an array of these which'll contain a cached list of
hostnames and IP addresses for a resolver part of my code.
To complicate matters, the array has to be available to child processes via
shm. Now, I'm pretty new to shm so I'm leaving that bit till last. Anyway,
in order to work with shm I need a pointer to an array of my struct
"cache_object". I've defined my pointer like this:
struct cache_object (*cache)[CACHESIZE];
HOSTNAME/IPSIZE/CACHESIZE are all #defined with integer values.
Now before I start work on the shm code I'm testing things with malloc()
because malloc will return a pointer to a piece of memory in the same way as
shmat(). (actually I wrote a load of shm code, couldn't get it to work and
removed it all in an attempt to get back to the root of the problem).
The problem I'm having, and this happened with my shm code as well was that
I can't seem to figure out how much memory I should be allowing myself to
store this array of structs. Here's the code I've got:
cache = malloc(sizeof(struct cache_object[CACHESIZE]));
as a sidenote, what should I typecast this to? I've tried:
cache = (struct *cache_object[CACHESIZE]) malloc(sizeof(struct
cache_object[CACHESIZE]));
but I get "syntax error before '*' token" from gcc.. I've tried:
cache = (struct cache_object[CACHESIZE]) malloc(sizeof(struct
cache_object[CACHESIZE]));
but I get "cast specifies array type"
Anyway, sizeof() should return the number of bytes I need to allocate in
order to store a CACHESIZE sized array of cache_object structs, correct?
Well, I thought so..
Running the following loop:
for (c=0;c<CACHESIZE;c++) {
printf("cache: %i ipaddr: %s hostname:
%s\n",c,cache[c]->ipaddr,cache[c]->hostname);
}
With these #defines:
#define HOSTSIZE 255
#define IPSIZE 255
#define CACHESIZE 10
Produces the following output:
cache: 0 ipaddr: hostname:
cache: 1 ipaddr: hostname:
cache: 2 ipaddr: hostname:
cache: 3 ipaddr: hostname:
Segmentation fault (core dumped)
Strangely, decreasing CACHESIZE to 5 prevents the segfault and the program
runs as expected:
$ ./caching_logger
foo 127.0.0.1 foo
cache: 0 ipaddr: hostname:
cache: 1 ipaddr: hostname:
cache: 2 ipaddr: hostname:
cache: 3 ipaddr: hostname:
cache: 4 ipaddr: hostname:
Any help with this would be very greatly appreciated, it's been driving me
nuts all day.
Incase anyone's interested, the code I'm working on sits on the end of a log
pipe from apache splitting out log lines for each vhost and logging them to
separate files, it also resolves IP addresses in the log lines to dns wait
time in apache itself. The main purpose of the program however is to
overcome apache's open file descriptor limit by requiring only one pipe to
this program - the program itself closes and re-opens each log file between
writes; less efficient, but necessary in the situation I run.
Below is the code I have so far (fork commented out to remove the need for
shm):
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <signal.h>
#define HOSTSIZE 255
#define IPSIZE 255
#define CACHESIZE 10
struct cache_object {
char hostname[HOSTSIZE+1];
char ipaddr[IPSIZE+1];
};
struct cache_object (*cache)[CACHESIZE];
int *cachecount;
int main () {
char vhost[HOSTSIZE+1], ip[IPSIZE], line[2046], path[255],
finalhost[HOSTSIZE+1];
FILE *outstream;
struct in_addr iph;
struct hostent *hp;
int c;
signal(SIGCHLD, SIG_IGN);
cache = malloc(sizeof(struct cache_object[CACHESIZE]));
cachecount = (int *) malloc(sizeof(int));
*cachecount=0;
while (!feof(stdin)) {
memset(vhost,0,255);
memset(ip,0,255);
memset(line,0,2046);
memset(path,0,255);
memset(finalhost,0,255);
fscanf(stdin, "%s %s ", vhost, ip);
fgets(line, 2046, stdin);
for (c=0;c<CACHESIZE;c++) {
printf("cache: %i ipaddr: %s hostname:
%s\n",c,cache[c]->ipaddr,cache[c]->hostname);
}
// if (fork() == 0) {
sprintf(path,"/home/logs/access_logs/%s",vhost);
if (inet_aton(ip, &iph)) {
if ((hp=gethostbyaddr((const char *)&iph,
sizeof(struct in_addr), AF_INET)) != NULL) {
sprintf(finalhost,"%s",hp->h_name);
} else {
sprintf(finalhost,"%s",ip);
}
} else {
sprintf(finalhost,"%s",ip);
}
sprintf(cache[*cachecount]->ipaddr,"%s",ip);
sprintf(cache[*cachecount]->hostname,"%s",finalhost);
if (*cachecount < CACHESIZE) {
*cachecount = *cachecount + 1;
} else {
*cachecount=0;
}
outstream = fopen(path, "a");
if (outstream != NULL) {
fprintf(outstream,"%s %s",finalhost, line);
fclose(outstream);
}
// exit(0);
// }
}
exit(0);
}
--
~Kieran Simkin
Digital Crocus
http://digital-crocus.com/
I wonder if anyone can help me, I've been headscratching for a few hours
over this.
Basically, I've defined a struct called cache_object:
struct cache_object {
char hostname[HOSTSIZE+1];
char ipaddr[IPSIZE+1];
};
I plan to store an array of these which'll contain a cached list of
hostnames and IP addresses for a resolver part of my code.
To complicate matters, the array has to be available to child processes via
shm. Now, I'm pretty new to shm so I'm leaving that bit till last. Anyway,
in order to work with shm I need a pointer to an array of my struct
"cache_object". I've defined my pointer like this:
struct cache_object (*cache)[CACHESIZE];
HOSTNAME/IPSIZE/CACHESIZE are all #defined with integer values.
Now before I start work on the shm code I'm testing things with malloc()
because malloc will return a pointer to a piece of memory in the same way as
shmat(). (actually I wrote a load of shm code, couldn't get it to work and
removed it all in an attempt to get back to the root of the problem).
The problem I'm having, and this happened with my shm code as well was that
I can't seem to figure out how much memory I should be allowing myself to
store this array of structs. Here's the code I've got:
cache = malloc(sizeof(struct cache_object[CACHESIZE]));
as a sidenote, what should I typecast this to? I've tried:
cache = (struct *cache_object[CACHESIZE]) malloc(sizeof(struct
cache_object[CACHESIZE]));
but I get "syntax error before '*' token" from gcc.. I've tried:
cache = (struct cache_object[CACHESIZE]) malloc(sizeof(struct
cache_object[CACHESIZE]));
but I get "cast specifies array type"
Anyway, sizeof() should return the number of bytes I need to allocate in
order to store a CACHESIZE sized array of cache_object structs, correct?
Well, I thought so..
Running the following loop:
for (c=0;c<CACHESIZE;c++) {
printf("cache: %i ipaddr: %s hostname:
%s\n",c,cache[c]->ipaddr,cache[c]->hostname);
}
With these #defines:
#define HOSTSIZE 255
#define IPSIZE 255
#define CACHESIZE 10
Produces the following output:
cache: 0 ipaddr: hostname:
cache: 1 ipaddr: hostname:
cache: 2 ipaddr: hostname:
cache: 3 ipaddr: hostname:
Segmentation fault (core dumped)
Strangely, decreasing CACHESIZE to 5 prevents the segfault and the program
runs as expected:
$ ./caching_logger
foo 127.0.0.1 foo
cache: 0 ipaddr: hostname:
cache: 1 ipaddr: hostname:
cache: 2 ipaddr: hostname:
cache: 3 ipaddr: hostname:
cache: 4 ipaddr: hostname:
Any help with this would be very greatly appreciated, it's been driving me
nuts all day.
Incase anyone's interested, the code I'm working on sits on the end of a log
pipe from apache splitting out log lines for each vhost and logging them to
separate files, it also resolves IP addresses in the log lines to dns wait
time in apache itself. The main purpose of the program however is to
overcome apache's open file descriptor limit by requiring only one pipe to
this program - the program itself closes and re-opens each log file between
writes; less efficient, but necessary in the situation I run.
Below is the code I have so far (fork commented out to remove the need for
shm):
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <signal.h>
#define HOSTSIZE 255
#define IPSIZE 255
#define CACHESIZE 10
struct cache_object {
char hostname[HOSTSIZE+1];
char ipaddr[IPSIZE+1];
};
struct cache_object (*cache)[CACHESIZE];
int *cachecount;
int main () {
char vhost[HOSTSIZE+1], ip[IPSIZE], line[2046], path[255],
finalhost[HOSTSIZE+1];
FILE *outstream;
struct in_addr iph;
struct hostent *hp;
int c;
signal(SIGCHLD, SIG_IGN);
cache = malloc(sizeof(struct cache_object[CACHESIZE]));
cachecount = (int *) malloc(sizeof(int));
*cachecount=0;
while (!feof(stdin)) {
memset(vhost,0,255);
memset(ip,0,255);
memset(line,0,2046);
memset(path,0,255);
memset(finalhost,0,255);
fscanf(stdin, "%s %s ", vhost, ip);
fgets(line, 2046, stdin);
for (c=0;c<CACHESIZE;c++) {
printf("cache: %i ipaddr: %s hostname:
%s\n",c,cache[c]->ipaddr,cache[c]->hostname);
}
// if (fork() == 0) {
sprintf(path,"/home/logs/access_logs/%s",vhost);
if (inet_aton(ip, &iph)) {
if ((hp=gethostbyaddr((const char *)&iph,
sizeof(struct in_addr), AF_INET)) != NULL) {
sprintf(finalhost,"%s",hp->h_name);
} else {
sprintf(finalhost,"%s",ip);
}
} else {
sprintf(finalhost,"%s",ip);
}
sprintf(cache[*cachecount]->ipaddr,"%s",ip);
sprintf(cache[*cachecount]->hostname,"%s",finalhost);
if (*cachecount < CACHESIZE) {
*cachecount = *cachecount + 1;
} else {
*cachecount=0;
}
outstream = fopen(path, "a");
if (outstream != NULL) {
fprintf(outstream,"%s %s",finalhost, line);
fclose(outstream);
}
// exit(0);
// }
}
exit(0);
}
--
~Kieran Simkin
Digital Crocus
http://digital-crocus.com/