Hi There,
I have a function called getdir() and strace is telling me that
there's a segmentation fault appearing in that function.
I am not able to locate the position where the seg fault may appear
cause my strace output looks like:
[pid 30211] stat("/usr/share/NovaxTSP/", {st_mode=S_IFDIR|0755,
st_size=1024, ...}) = 0
[pid 30211] open("/usr/share/NovaxTSP/", O_RDONLY) = 17
[pid 30211] fcntl(17, F_SETFD, FD_CLOEXEC) = 0
[pid 30211] getdents(17, /* 13 entries */, 3933) = 308
[pid 30211] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
where "/usr/share/NovaxTSP/" is the path that i'm passing to my
function:
int getdir(char *path, char ***filelist)
{
int items=0;
char **temp=NULL;
char filename[1024]={0};
struct dirent *dp;
DIR *dir = opendir(path);
if (dir==NULL){
syslog(LOG_NOTICE, "nlog: Error opening log_record directory %s,
Errno: %s", path, strerror( errno ));
printf("Error opening log_record directory %s, Errno: %s", path,
strerror( errno ));
return -1;
}
while((dp=readdir(dir))!=NULL){
if(strstr(dp->d_name, "log_record")!=NULL){
snprintf(filename,sizeof(filename),"%s%s",path,dp->d_name);
temp = realloc((*filelist), (items+1) * sizeof(*temp));
if (temp == NULL) {
while (--items >= 0)
free ((*filelist)[items]);
free ((*filelist));
syslog(LOG_NOTICE, "nlog: Error reallocating memory in filelist
\n");
printf("Error reallocating memory for filelist\n");
closedir(dir);
return -1;
}
(*filelist) = temp;
(*filelist)[items] = malloc(strlen(filename)+1);
if ((*filelist)[items] == NULL) {
syslog(LOG_NOTICE, "nlog: Error allocating memory for filename
\n");
return -1;
}
strcpy ((*filelist)[items], filename);
++items;
}
}
closedir(dir);
return items;
}
Does anyone see how this segmentation fault may appear?
Thank you!
--
roN
|
|
0
|
|
|
|
Reply
|
cerr
|
1/15/2010 9:07:00 PM |
|
In <db7c2087-dfb6-4dd5-a54d-a7aa15757773@j5g2000yqm.googlegroups.com> cerr <ron.eggler@gmail.com> writes:
> int getdir(char *path, char ***filelist)
> {
> ...
> }
> Does anyone see how this segmentation fault may appear?
> Thank you!
This isn't a complete program. It has no main(), so we don't know how
you're calling getdir().
Please post the complete program.
--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"
|
|
0
|
|
|
|
Reply
|
John
|
1/15/2010 9:45:47 PM
|
|
On Jan 15, 1:45=A0pm, John Gordon <gor...@panix.com> wrote:
> In <db7c2087-dfb6-4dd5-a54d-a7aa15757...@j5g2000yqm.googlegroups.com> cer=
r <ron.egg...@gmail.com> writes:
>
> > int getdir(char *path, char ***filelist)
> > {
> > =A0...
> > }
> > Does anyone see how this segmentation fault may appear?
> > Thank you!
>
> This isn't a complete program. =A0It has no main(), so we don't know how
> you're calling getdir().
>
> Please post the complete program.
Well, I can't post the complete application but I call it roughly like
this:
void main (void)
{
char *FilePath=3D"/usr/share/NovaxTSP/";
int files;
while (1)
{
files=3Dgetdir(FilePath, &list);
}
}
|
|
0
|
|
|
|
Reply
|
cerr
|
1/15/2010 10:53:17 PM
|
|
In <b3e93e22-eb90-4684-a8d9-ed156bd79462@q4g2000yqm.googlegroups.com> cerr <ron.eggler@gmail.com> writes:
> Well, I can't post the complete application but I call it roughly like
> this:
> void main (void)
> {
> char *FilePath=3D"/usr/share/NovaxTSP/";
> int files;
> while (1)
> {
> files=3Dgetdir(FilePath, &list);
> }
> }
What is "list"? You haven't declared it.
--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"
|
|
0
|
|
|
|
Reply
|
John
|
1/15/2010 10:56:26 PM
|
|
On Jan 15, 2:56=A0pm, John Gordon <gor...@panix.com> wrote:
> In <b3e93e22-eb90-4684-a8d9-ed156bd79...@q4g2000yqm.googlegroups.com> cer=
r <ron.egg...@gmail.com> writes:
>
> > Well, I can't post the complete application but I call it roughly like
> > this:
> > void main (void)
> > {
> > char *FilePath=3D3D"/usr/share/NovaxTSP/";
> > int files;
> > while (1)
> > {
> > files=3D3Dgetdir(FilePath, &list);
> > }
> > }
>
> What is "list"? =A0You haven't declared it.
Oh yeah, sorry!
List is declared like:
char **list;
|
|
0
|
|
|
|
Reply
|
cerr
|
1/15/2010 11:10:52 PM
|
|
On 1/15/2010 6:10 PM, cerr wrote:
> On Jan 15, 2:56 pm, John Gordon<gor...@panix.com> wrote:
>> In<b3e93e22-eb90-4684-a8d9-ed156bd79...@q4g2000yqm.googlegroups.com> cerr<ron.egg...@gmail.com> writes:
>>
>>> Well, I can't post the complete application but I call it roughly like
>>> this:
>>> void main (void)
>>> {
>>> char *FilePath=3D"/usr/share/NovaxTSP/";
>>> int files;
>>> while (1)
>>> {
>>> files=3Dgetdir(FilePath,&list);
>>> }
>>> }
>>
>> What is "list"? You haven't declared it.
> Oh yeah, sorry!
> List is declared like:
> char **list;
An uninitialized auto variable has indeterminate value.
When you pass that indeterminate value to realloc() (inside
your getdir() function), there's no telling what will happen.
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
1/15/2010 11:12:58 PM
|
|
On Jan 15, 3:12=A0pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
> On 1/15/2010 6:10 PM, cerr wrote:
>
>
>
>
>
> > On Jan 15, 2:56 pm, John Gordon<gor...@panix.com> =A0wrote:
> >> In<b3e93e22-eb90-4684-a8d9-ed156bd79...@q4g2000yqm.googlegroups.com> =
=A0cerr<ron.egg...@gmail.com> =A0writes:
>
> >>> Well, I can't post the complete application but I call it roughly lik=
e
> >>> this:
> >>> void main (void)
> >>> {
> >>> char *FilePath=3D3D"/usr/share/NovaxTSP/";
> >>> int files;
> >>> while (1)
> >>> {
> >>> files=3D3Dgetdir(FilePath,&list);
> >>> }
> >>> }
>
> >> What is "list"? =A0You haven't declared it.
> > Oh yeah, sorry!
> > List is declared like:
> > char **list;
>
> =A0 =A0 =A0An uninitialized auto variable has indeterminate value.
> When you pass that indeterminate value to realloc() (inside
> your getdir() function), there's no telling what will happen.
Exactly, that's why I set it to NULL:
list=3DNULL;
which i also didn't paste, sorry...
>
> --
> Eric Sosman
> esos...@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
cerr
|
1/16/2010 12:02:51 AM
|
|
cerr <ron.eggler@gmail.com> wrote:
> I have a function called getdir() and strace is telling me that
> there's a segmentation fault appearing in that function.
> I am not able to locate the position where the seg fault may appear
> cause my strace output looks like:
> [pid 30211] stat("/usr/share/NovaxTSP/", {st_mode=S_IFDIR|0755,
> st_size=1024, ...}) = 0
> [pid 30211] open("/usr/share/NovaxTSP/", O_RDONLY) = 17
> [pid 30211] fcntl(17, F_SETFD, FD_CLOEXEC) = 0
> [pid 30211] getdents(17, /* 13 entries */, 3933) = 308
> [pid 30211] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
> where "/usr/share/NovaxTSP/" is the path that i'm passing to my
> function:
To me it's not totally obvious that the segmentation fault
occurs in the function getdir() - the strace output just says
that it happens sometime after a call of getdens(). It might
be in the call of your getdir() function but that's not a
100% certainty, at least as far as I can tell. So you might be
looking at the wrong place when searching for the problem. If
you can use a debugger things would be a lot easier since it
would tell you exactly the line where the SIGSEGV happens...
> int getdir(char *path, char ***filelist)
> {
> int items=0;
> char **temp=NULL;
> char filename[1024]={0};
> struct dirent *dp;
> DIR *dir = opendir(path);
> if (dir==NULL){
> syslog(LOG_NOTICE, "nlog: Error opening log_record directory %s,
> Errno: %s", path, strerror( errno ));
> printf("Error opening log_record directory %s, Errno: %s", path,
> strerror( errno ));
> return -1;
> }
> while((dp=readdir(dir))!=NULL){
> if(strstr(dp->d_name, "log_record")!=NULL){
> snprintf(filename,sizeof(filename),"%s%s",path,dp->d_name);
> temp = realloc((*filelist), (items+1) * sizeof(*temp));
> if (temp == NULL) {
> while (--items >= 0)
> free ((*filelist)[items]);
> free ((*filelist));
> syslog(LOG_NOTICE, "nlog: Error reallocating memory in filelist
> \n");
> printf("Error reallocating memory for filelist\n");
> closedir(dir);
> return -1;
> }
> (*filelist) = temp;
> (*filelist)[items] = malloc(strlen(filename)+1);
> if ((*filelist)[items] == NULL) {
> syslog(LOG_NOTICE, "nlog: Error allocating memory for filename
> \n");
> return -1;
> }
> strcpy ((*filelist)[items], filename);
> ++items;
> }
> }
> closedir(dir);
> return items;
> }
> Does anyone see how this segmentation fault may appear?
Not something obvious (after I reformated your code a bit to make
it easier to read;-). But there are some things you really must
make sure when calling that function:
a) 'path' may not be a NULL pointer
b) what 'filelist' points to must be either NULL or point to
memory that you got from malloc() or realloc() (and which
wasn't deallocated before the call of this function)
If one of these conditions isn't satisfied then the call of the
function rather likely will result in a SIGSEGV.
There are some things that I don't like about this function:
If the allocation for the file list fails then you call free()
on '*filelist' but you don't set it to NULL. Unless you are
careful in the caller and set 'filelist' to NULL if the function
returns -1 then the callers version of 'filelist' will still be
something non-NULL even though it's not a pointer you're allowed
to use anymore. A subsequent call of getdir() then will pass a
value in 'filelist' that's not a pointer you're allowed to use
in realloc(). And while you do some error checking you assume
several things to end up fine without actually testing. And, of
course, the name of the function is a bit of a misnomer, some-
thing like get_log_files_in_dir() would be more suitable;-)
Also a side-effect of a successful call of the function is
that what 'filelist' was pointing to before might be lost.
That might be intended but it's something that might not be
obvious to someone calling the function...
Here's a (untested!!!) version of your function that might be
a bit easier to maintain and is hopefully a bit more thorough
when it comes to error checking. It also avoids using fixed
lengths for file names, doesn't change what 'filelist' points
to in case of failed allocations (or no fitting files in the
directory) and also doesn't leak memory when allocation for a
file name fails:
int
getdir( const char * path,
char *** filelist )
{
int items = 0;
char ** fl = *filelist;
char ** tmp;
struct dirent * dp;
DIR * dir;
size_t path_len;
/* Check that path argument isn't a NULL pointer */
if ( ! path )
{
syslog( LOG_NOTICE, "nlog: 'path' argument is NULL in call of "
"getdir()\n" );
fprintf( stderr, "'path' argument is NULL in call of getdir()\n" );
return -1;
}
/* Check that 'path' is ok (take into account the possibility that
'path' could be an empty string) */
if ( ! *path || path[ ( path_len = strlen( path ) ) - 1 ] != '/' )
{
syslog( LOG_NOTICE, "nlog: 'path' doesn't end in '/' in call of "
"getdir()\n" );
fprintf( stderr, "'path' doesn't end in '/' in call of getdir()\n" );
return -1;
}
/* Try to open the directory */
if ( ! ( dir = opendir( path ) ) )
{
syslog( LOG_NOTICE, "nlog: Error opening log_record directory %s, "
"Errno: %s", path, strerror( errno ) );
fprintf( stderr, "Error opening log_record directory %s, Errno: %s",
path, strerror( errno ) );
return -1;
}
/* Loop over all files in the directory and do sonething about the
files that contain the string "log_record" */
while ( ( dp = readdir( dir ) )
{
if ( ! strstr( dp->d_name, "log_record" ) )
continue;
/* Extend the file list array and get enough memory for the
file name (with path) */
if ( ! ( tmp = realloc( fl, ( items + 1 ) * sizeof *tmp ) )
|| ! ( tmp[ items ] = malloc( path_len
+ strlen( dp->d_name ) + 1 ) ) )
{
closedir( dir );
while ( --items >= 0 )
free ( fl[ items ] );
free( fl );
if ( ! tmp )
{
syslog( LOG_NOTICE, "nlog: Error reallocating memory for "
"filelist\n");
fprintf( stderr, "Error reallocating memory for filelist\n" );
}
else
{
syslog( LOG_NOTICE, "nlog: Error allocating memory for "
"filename\n");
fprintf( stderr, "Error allocating memory for filename\n");
}
return -1;
}
sprintf( tmp[ items++ ], "%s%s", path, dp->d_name );
fl = tmp;
}
closedir( dir );
*filelist = fl;
return items;
}
What can't be done is checking that the 'filelist' argument is
correct, you have to make sure it's a "good" pointer (i.e. either
NULL or pointing to allocated memory) by other means.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/16/2010 1:57:14 AM
|
|
In article <7rcknqFpuaU1@mid.uni-berlin.de>,
jt@toerring.de (Jens Thoms Toerring) wrote:
> cerr <ron.eggler@gmail.com> wrote:
> > I have a function called getdir() and strace is telling me that
> > there's a segmentation fault appearing in that function.
> > I am not able to locate the position where the seg fault may appear
> > cause my strace output looks like:
> > [pid 30211] stat("/usr/share/NovaxTSP/", {st_mode=S_IFDIR|0755,
> > st_size=1024, ...}) = 0
> > [pid 30211] open("/usr/share/NovaxTSP/", O_RDONLY) = 17
> > [pid 30211] fcntl(17, F_SETFD, FD_CLOEXEC) = 0
> > [pid 30211] getdents(17, /* 13 entries */, 3933) = 308
> > [pid 30211] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
>
> > where "/usr/share/NovaxTSP/" is the path that i'm passing to my
> > function:
>
> To me it's not totally obvious that the segmentation fault
> occurs in the function getdir() - the strace output just says
> that it happens sometime after a call of getdens(). It might
> be in the call of your getdir() function but that's not a
> 100% certainty, at least as far as I can tell. So you might be
> looking at the wrong place when searching for the problem. If
> you can use a debugger things would be a lot easier since it
> would tell you exactly the line where the SIGSEGV happens...
And even if the segmentation fault occurs in getdir(), that doesn't mean
the *problem* is in getdir(). A segmentation fault is usually due to
indirecting through an invalid pointer. If some other part of the
program stomped on a pointer, but it's not used until you get into
getdir(), that's when the error will be noticed.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
|
|
0
|
|
|
|
Reply
|
Barry
|
1/16/2010 3:30:26 AM
|
|
On 1/15/2010 7:02 PM, cerr wrote:
> On Jan 15, 3:12 pm, Eric Sosman<esos...@ieee-dot-org.invalid> wrote:
>> On 1/15/2010 6:10 PM, cerr wrote:
>>
>>
>>
>>
>>
>>> On Jan 15, 2:56 pm, John Gordon<gor...@panix.com> wrote:
>>>> [...]
>>>> What is "list"? You haven't declared it.
>>> Oh yeah, sorry!
>>> List is declared like:
>>> char **list;
>>
>> An uninitialized auto variable has indeterminate value.
>> When you pass that indeterminate value to realloc() (inside
>> your getdir() function), there's no telling what will happen.
> Exactly, that's why I set it to NULL:
> list=NULL;
> which i also didn't paste, sorry...
Are you sure it's wise to show us an entire line, all at
once? Maybe you should dribble out your code a little more
slowly, one keyword or even just one character at a time. The
game is *so* much fun; please prolong it just as long as you can.
One thing you've done quite well is to conceal the order of
the lines you've divulged, which helps string things along. With
N lines of code we've got factorial N possible programs to think
about. A lot of them won't even compile, but a large number of
candidates still remain for our entertainment. Adding in the
fact that we don't even know whether it's N or N+1 or N+K lines --
Oh, yes, I think you can keep the game going indefinitely!
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
1/16/2010 2:25:14 PM
|
|
If you can't post your program because it is too big, you could try
reproducing the problem with a smaller program with the essential
elements, and post the whole of the smaller program.
In fact, it might be a useful exercise to reduce the code down anyway,
to eliminate which bit is causing the problem.
Just a thought.
|
|
0
|
|
|
|
Reply
|
neilsolent
|
1/16/2010 3:59:42 PM
|
|
neilsolent wrote:
> If you can't post your program because it is too big, you could try
> reproducing the problem with a smaller program with the essential
> elements, and post the whole of the smaller program.
> In fact, it might be a useful exercise to reduce the code down anyway,
> to eliminate which bit is causing the problem.
>
> Just a thought.
>
Since I've got similar interests and OP is slow to the punch, let me
show what I've got on this now:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <syslog.h>
int getdir(const char *, char ***filelist);
int main(void)
{
char **list;
char *FilePath="/home/dan/source/";
int files;
files=getdir(FilePath, &list);
printf("files is %d\n", files);
return 0;
}
int
getdir( const char * path,
char *** filelist )
{
int items = 0;
char ** fl = *filelist;
char ** tmp;
struct dirent * dp;
DIR * dir;
size_t path_len;
/* Check that path argument isn't a NULL pointer */
if ( ! path )
{
syslog( LOG_NOTICE, "nlog: 'path' argument is NULL in call of "
"getdir()\n" );
fprintf( stderr, "'path' argument is NULL in call of getdir()\n" );
return -1;
}
/* Check that 'path' is ok (take into account the possibility that
'path' could be an empty string) */
if ( ! *path || path[ ( path_len = strlen( path ) ) - 1 ] != '/' )
{
syslog( LOG_NOTICE, "nlog: 'path' doesn't end in '/' in call of "
"getdir()\n" );
fprintf( stderr, "'path' doesn't end in '/' in call of
getdir()\n" );
return -1;
}
/* Try to open the directory */
if ( ! ( dir = opendir( path ) ) )
{
syslog( LOG_NOTICE, "nlog: Error opening log_record directory %s, "
"Errno: %s", path, strerror( errno ) );
fprintf( stderr, "Error opening log_record directory %s, Errno:
%s",
path, strerror( errno ) );
return -1;
}
/* Loop over all files in the directory and do sonething about the
files that contain the string "log_record" */
while ( ( dp = readdir( dir ) ) )
{
if ( ! strstr( dp->d_name, "log_record" ) )
continue;
/* Extend the file list array and get enough memory for the
file name (with path) */
if ( ! ( tmp = realloc( fl, ( items + 1 ) * sizeof *tmp ) )
|| ! ( tmp[ items ] = malloc( path_len
+ strlen( dp->d_name ) + 1 ) ) )
{
closedir( dir );
while ( --items >= 0 )
free ( fl[ items ] );
free( fl );
if ( ! tmp )
{
syslog( LOG_NOTICE, "nlog: Error reallocating memory for "
"filelist\n");
fprintf( stderr, "Error reallocating memory for
filelist\n" );
}
else
{
syslog( LOG_NOTICE, "nlog: Error allocating memory for "
"filename\n");
fprintf( stderr, "Error allocating memory for filename\n");
}
return -1;
}
sprintf( tmp[ items++ ], "%s%s", path, dp->d_name );
fl = tmp;
}
closedir( dir );
*filelist = fl;
return items;
}
// gcc -std=c99 -Wall -Wextra rd7.c -o out
So this is OP's code with several things cleaned up. I added headers
and a proper caller. It's Jens' elsethread getdir(), with the exception
that I added a third right parenthesis to his while control.
When I run this, I get zero, but it compiles. I hope I'm not doing
someone's homework, but this is literally my homework tonight, now that
I don't want to go anywhere beyond computer, tv, WC and bed tonight.
One thing I don't see is how the caller is going to know how big to make
the list big enough, and how to shake out the data as the the directory
is processed.
--
frank
|
|
0
|
|
|
|
Reply
|
frank
|
1/17/2010 3:36:21 AM
|
|
frank <frank@example.invalid> wrote:
> Since I've got similar interests and OP is slow to the punch, let me
> show what I've got on this now:
> int getdir(const char *, char ***filelist);
> int main(void)
> {
> char **list;
> char *FilePath="/home/dan/source/";
> int files;
> files=getdir(FilePath, &list);
Now you made just the mistake I tried to warn against: due to
the way the getdir() function was designed by the OP it expects
(a pointer to) a pointer as the second argument that's either
NULL or has been obtained via malloc() or realloc(). But what
you pass it here is an uninitialized pointer ('list' is an
automatic variable, so it will hold a garbage value unless
explicitely initialized). That will lead to a segmentation
fault (or even worse, memory corruption, if 'list' by sheer
bad luck contains a valid pointer to allocated memory) within
getdir() when a file is found that fits the requested pattern
(i.e. has "log_record" somewhere in its name).
Personally, I don't think it's a good idea to insist on getting
a valid pointer passed to getdir() for two reasons: it's too
easy to forget about that requirement and even when done cor-
rectly there are too many chances for creating memory leaks.
Just imagine you call it twice like that:
list = NULL;
num_files = getdir( FilePath_A, &list );
num_file = getdir( FilePath_B, &list );
It's easy to overlook that this, while being two otherwise
correct calls, introduces a memory leak in case the first
call found at least a single file. To avoid that you would
have to do
list = NULL;
num_files = getdir( FilePath_A, &list );
while ( num_files > 0 )
free( list[ --num_files ] );
num_file = getdir( FilePath_B, &list );
For the user of the function it's rather unintuitive to not
have to free() what 'list' pointo to while having to free()
what the elements of 'list' point to...
If I were to "redesign" the function I probably would have
getdir() take only the path argument and have it return a
pointer to the file list, with the modification that the
file list always ends in a NULL pointer to mark its end -
that way you don't have to also keep track of how many
elements it has. And then I'ld supply a second function,
free_dir_list(), which receives the file list and free()'s
everthing in it.
> One thing I don't see is how the caller is going to know how big to make
> the list big enough, and how to shake out the data as the the directory
> is processed.
Since not the caller is creating the list it doesn't need to
know in advance how big the list has to be - getdir() is crea-
ting the list. And I have no idea what you mean with "shake
out the data", sorry;-)
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/17/2010 12:18:24 PM
|
|
Hallo group! (sorry, my english is bad :)
I followed the thread and just for nostalgic reasons i want to present
my solution. I wrote it more than 20 years ago on a SCO Xenix box on an
intel 386 processor with 16 MHz and 2 MB of RAM. Compiled with gcc
version 1.40 :)
It has some extensions that you probably dont need:
- file sorting via qsort()
- saves lstat() struct information
- memory chunks are allocated for speed up
- no error-reporting, because i used it as a low-level function
Hope you enjoy it!
Heiko
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct {
char *name;
struct stat stat;
} FL;
typedef struct {
FL *fl;
int no_of_files;
} DI;
#define FL_CHUNK_SIZE 64
static int fl_name_cmp(FL *a, FL *b)
{
return strcmp(a->name, b->name);
}
void freedir(DI *d)
{
if (d == NULL)
return;
if (d->fl != NULL) {
while(d->no_of_files--)
free(d->fl[d->no_of_files].name);
free(d->fl);
}
free(d);
}
DI *getdir(char *cwd)
{
DIR *dirp;
struct dirent *dp;
struct stat st;
char *tmp;
DI *d;
dirp = opendir(cwd);
if (!dirp)
return NULL;
d = malloc(sizeof(DI));
if (d == NULL)
return NULL;
d->no_of_files = 0;
d->fl = NULL;
tmp = malloc(strlen(cwd) + NAME_MAX + 1);
if (tmp == NULL) {
free(d);
return NULL;
}
while((dp = readdir(dirp))) {
if (!(d->no_of_files % FL_CHUNK_SIZE)) {
d->fl = (d->fl == NULL ? malloc(sizeof(FL) * (d->no_of_files + FL_CHUNK_SIZE)) :
realloc(d->fl, sizeof(FL) * (d->no_of_files + FL_CHUNK_SIZE)));
if (d->fl == NULL) {
free(tmp);
free(d);
return NULL;
}
}
d->fl[d->no_of_files].name = strdup(dp->d_name);
if (d->fl[d->no_of_files].name == NULL) {
free(tmp);
freedir(d);
return NULL;
}
strcpy(tmp, cwd);
strcat(tmp, "/");
strcat(tmp, dp->d_name);
lstat(tmp, &st);
d->fl[d->no_of_files++].stat = st;
}
closedir(dirp);
free(tmp);
qsort(d->fl, d->no_of_files, sizeof(FL), (void *)fl_name_cmp);
return d;
}
// test
int main()
{
DI *d;
char *path = "/";
int i;
d = getdir(path);
if (d == NULL) {
fprintf(stderr, "%s: %s\n", path, strerror(errno));
exit(1);
}
for (i = 0 ; i < d->no_of_files ; i++)
printf("%8ld %s\n", d->fl[i].stat.st_size, d->fl[i].name);
freedir(d);
exit(0);
}
|
|
0
|
|
|
|
Reply
|
Heiko
|
1/17/2010 11:10:01 PM
|
|
Heiko Jappe wrote:
> Hallo group! (sorry, my english is bad :)
>
> I followed the thread and just for nostalgic reasons i want to present
> my solution. I wrote it more than 20 years ago on a SCO Xenix box on an
> intel 386 processor with 16 MHz and 2 MB of RAM. Compiled with gcc
> version 1.40 :)
>
> It has some extensions that you probably dont need:
>
> - file sorting via qsort()
> - saves lstat() struct information
> - memory chunks are allocated for speed up
> - no error-reporting, because i used it as a low-level function
>
> Hope you enjoy it!
> Heiko
[code elided]
Na, Heiko, VielenDank! I changed NAME_MAX to FILENAME_MAX and get output:
dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra rd8.c -o out
rd8.c: In function �getdir�:
rd8.c:77: warning: implicit declaration of function �strdup�
rd8.c:77: warning: assignment makes pointer from integer without a cast
rd8.c:86: warning: implicit declaration of function �lstat�
dan@dan-desktop:~/source$ ./out
4096 .
4096 ..
4096 bin
4096 boot
11 cdrom
3940 dev
12288 etc
4096 home
33 initrd.img
33 initrd.img.old
12288 lib
16384 lost+found
4096 media
4096 mnt
4096 opt
0 proc
4096 root
4096 sbin
4096 selinux
4096 srv
0 sys
4096 tmp
4096 usr
4096 var
30 vmlinuz
30 vmlinuz.old
dan@dan-desktop:~/source$
Can you (or someone else) tell me exactly what the integer value represents:
printf("%8ld %s\n", d->fl[i].stat.st_size, d->fl[i].name);
--
frank
|
|
0
|
|
|
|
Reply
|
frank
|
1/18/2010 12:13:21 AM
|
|
frank <frank@example.invalid> wrote:
> Heiko Jappe wrote:
> Na, Heiko, VielenDank! I changed NAME_MAX to FILENAME_MAX and get output:
> dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra rd8.c -o out
> dan@dan-desktop:~/source$ ./out
> 4096 .
> 4096 ..
> 4096 bin
> 4096 boot
> 11 cdrom
....
> dan@dan-desktop:~/source$
> Can you (or someone else) tell me exactly what the integer value represents:
> printf("%8ld %s\n", d->fl[i].stat.st_size, d->fl[i].name);
Did you already have a look at the man page 'man 2 lstat'? It
describes the 'stat' structure with some details, perhaps enough
to answer your question.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/18/2010 12:51:35 AM
|
|
On Jan 15, 5:57=A0pm, j...@toerring.de (Jens Thoms Toerring) wrote:
> cerr <ron.egg...@gmail.com> wrote:
> > I have a function called getdir() and strace is telling me that
> > there's a segmentation fault appearing in that function.
> > I am not able to locate the position where the seg fault may appear
> > cause my strace output looks like:
> > [pid 30211] stat("/usr/share/NovaxTSP/", {st_mode=3DS_IFDIR|0755,
> > st_size=3D1024, ...}) =3D 0
> > [pid 30211] open("/usr/share/NovaxTSP/", O_RDONLY) =3D 17
> > [pid 30211] fcntl(17, F_SETFD, FD_CLOEXEC) =3D 0
> > [pid 30211] getdents(17, /* 13 entries */, 3933) =3D 308
> > [pid 30211] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
> > where "/usr/share/NovaxTSP/" is the path that i'm passing to my
> > function:
>
> To me it's not totally obvious that the segmentation fault
> occurs in the function getdir() - the strace output just says
> that it happens sometime after a call of getdens(). It might
> be in the call of your getdir() function but that's not a
> 100% certainty, at least as far as I can tell. So you might be
> looking at the wrong place when searching for the problem. If
> you can use a debugger things would be a lot easier since it
> would tell you exactly the line where the SIGSEGV happens...
>
>
>
>
>
> > int getdir(char *path, char ***filelist)
> > {
> > =A0 int items=3D0;
> > =A0 char **temp=3DNULL;
> > =A0 char filename[1024]=3D{0};
> > =A0 struct dirent *dp;
> > =A0 DIR *dir =3D opendir(path);
> > =A0 if (dir=3D=3DNULL){
> > =A0 =A0 syslog(LOG_NOTICE, "nlog: Error opening log_record directory %s=
,
> > Errno: %s", path, strerror( errno ));
> > =A0 =A0 printf("Error opening log_record directory %s, Errno: %s", path=
,
> > strerror( errno ));
> > =A0 =A0 return -1;
> > =A0 }
> > =A0 while((dp=3Dreaddir(dir))!=3DNULL){
> > =A0 =A0 if(strstr(dp->d_name, "log_record")!=3DNULL){
> > =A0 =A0 =A0 snprintf(filename,sizeof(filename),"%s%s",path,dp->d_name);
> > =A0 =A0 =A0 temp =3D realloc((*filelist), (items+1) * sizeof(*temp));
> > =A0 =A0 =A0 if (temp =3D=3D NULL) {
> > =A0 =A0 =A0 =A0 while (--items >=3D 0)
> > =A0 =A0 =A0 =A0 =A0 free ((*filelist)[items]);
> > =A0 =A0 =A0 =A0 free ((*filelist));
> > =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog: Error reallocating memory in =
filelist
> > \n");
> > =A0 =A0 =A0 =A0 printf("Error reallocating memory for filelist\n");
> > =A0 =A0 =A0 =A0 closedir(dir);
> > =A0 =A0 =A0 =A0 return -1;
> > =A0 =A0 =A0 }
> > =A0 =A0 =A0 (*filelist) =3D temp;
> > =A0 =A0 =A0 (*filelist)[items] =3D malloc(strlen(filename)+1);
> > =A0 =A0 =A0 if ((*filelist)[items] =3D=3D NULL) {
> > =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog: Error allocating memory for f=
ilename
> > \n");
> > =A0 =A0 =A0 =A0 return -1;
> > =A0 =A0 =A0 }
> > =A0 =A0 =A0 strcpy ((*filelist)[items], filename);
> > =A0 =A0 =A0 ++items;
> > =A0 =A0 }
> > =A0 }
> > =A0 closedir(dir);
> > =A0 return items;
> > }
> > Does anyone see how this segmentation fault may appear?
>
> Not something obvious (after I reformated your code a bit to make
> it easier to read;-). But there are some things you really must
> make sure when calling that function:
>
> a) 'path' may not be a NULL pointer
> b) what 'filelist' points to must be either NULL or point to
> =A0 =A0memory that you got from malloc() or realloc() (and which
> =A0 =A0wasn't deallocated before the call of this function)
>
> If one of these conditions isn't satisfied then the call of the
> function rather likely will result in a SIGSEGV.
>
> There are some things that I don't like about this function:
> If the allocation for the file list fails then you call free()
> on '*filelist' but you don't set it to NULL. Unless you are
> careful in the caller and set 'filelist' to NULL if the function
> returns -1 then the callers version of 'filelist' will still be
> something non-NULL even though it's not a pointer you're allowed
> to use anymore. A subsequent call of getdir() then will pass a
> value in 'filelist' that's not a pointer you're allowed to use
> in realloc(). And while you do some error checking you assume
> several things to end up fine without actually testing. And, of
> course, the name of the function is a bit of a misnomer, some-
> thing like get_log_files_in_dir() would be more suitable;-)
>
> Also a side-effect of a successful call of the function is
> that what 'filelist' was pointing to before might be lost.
> That might be intended but it's something that might not be
> obvious to someone calling the function...
>
> Here's a (untested!!!) version of your function that might be
> a bit easier to maintain and is hopefully a bit more thorough
> when it comes to error checking. It also avoids using fixed
> lengths for file names, doesn't change what 'filelist' points
> to in case of failed allocations (or no fitting files in the
> directory) and also doesn't leak memory when allocation for a
> file name fails:
>
> int
> getdir( const char =A0 * path,
> =A0 =A0 =A0 =A0 char =A0 =A0 =A0 *** filelist )
> {
> =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0items =3D 0;
> =A0 =A0 char =A0 =A0 =A0 =A0 =A0** fl =3D *filelist;
> =A0 =A0 char =A0 =A0 =A0 =A0 =A0** tmp;
> =A0 =A0 struct dirent =A0* dp;
> =A0 =A0 DIR =A0 =A0 =A0 =A0 =A0 =A0* dir;
> =A0 =A0 size_t =A0 =A0 =A0 =A0 =A0 path_len;
>
> =A0 =A0 /* Check that path argument isn't a NULL pointer */
>
> =A0 =A0 if ( ! path )
> =A0 =A0 {
> =A0 =A0 =A0 =A0 syslog( LOG_NOTICE, "nlog: 'path' argument is NULL in cal=
l of "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "getdir()\n" );
> =A0 =A0 =A0 =A0 fprintf( stderr, "'path' argument is NULL in call of getd=
ir()\n" );
> =A0 =A0 =A0 =A0 return -1;
> =A0 =A0 }
>
> =A0 =A0 /* Check that 'path' is ok (take into account the possibility tha=
t
> =A0 =A0 =A0 =A0'path' could be an empty string) */
>
> =A0 =A0 if ( ! *path || path[ ( path_len =3D strlen( path ) ) - 1 ] !=3D =
'/' )
> =A0 =A0 {
> =A0 =A0 =A0 =A0 syslog( LOG_NOTICE, "nlog: 'path' doesn't end in '/' in c=
all of "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "getdir()\n" );
> =A0 =A0 =A0 =A0 fprintf( stderr, "'path' doesn't end in '/' in call of ge=
tdir()\n" );
> =A0 =A0 =A0 =A0 return -1;
> =A0 =A0 }
>
> =A0 =A0 /* Try to open the directory */
>
> =A0 =A0 if ( ! ( dir =3D opendir( path ) ) )
> =A0 =A0 {
> =A0 =A0 =A0 =A0 syslog( LOG_NOTICE, "nlog: Error opening log_record direc=
tory %s, "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "Errno: %s", path, strerror( errno ) );
> =A0 =A0 =A0 =A0 fprintf( stderr, "Error opening log_record directory %s, =
Errno: %s",
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0path, strerror( errno ) );
> =A0 =A0 =A0 =A0 return -1;
> =A0 =A0 }
>
> =A0 =A0 /* Loop over all files in the directory and do sonething about th=
e
> =A0 =A0 =A0 =A0files that contain the string "log_record" */
>
> =A0 =A0 while ( ( dp =3D readdir( dir ) )
> =A0 =A0 {
> =A0 =A0 =A0 =A0 if ( ! strstr( dp->d_name, "log_record" ) )
> =A0 =A0 =A0 =A0 =A0 =A0 continue;
>
> =A0 =A0 =A0 =A0 /* Extend the file list array and get enough memory for t=
he
> =A0 =A0 =A0 =A0 =A0 =A0file name (with path) */
>
> =A0 =A0 =A0 =A0 if ( =A0 =A0! ( tmp =3D realloc( fl, ( items + 1 ) * size=
of *tmp ) )
> =A0 =A0 =A0 =A0 =A0 =A0 =A0|| ! ( tmp[ items ] =3D malloc( =A0 path_len
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0+ strlen( dp->d_name ) + 1 ) ) )
> =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 closedir( dir );
>
> =A0 =A0 =A0 =A0 =A0 =A0 while ( --items >=3D 0 )
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free ( fl[ items ] );
> =A0 =A0 =A0 =A0 =A0 =A0 free( fl );
>
> =A0 =A0 =A0 =A0 =A0 =A0 if ( ! tmp )
> =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog( LOG_NOTICE, "nlog: Error realloca=
ting memory for "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "filelist\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf( stderr, "Error reallocating memo=
ry for filelist\n" );
> =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog( LOG_NOTICE, "nlog: Error allocati=
ng memory for "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "filename\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf( stderr, "Error allocating memory=
for filename\n");
> =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 return -1;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 sprintf( tmp[ items++ ], "%s%s", path, dp->d_name );
> =A0 =A0 =A0 =A0 fl =3D tmp;
> =A0 =A0 }
>
> =A0 =A0 closedir( dir );
> =A0 =A0 *filelist =3D fl;
> =A0 =A0 return items;
>
> }
>
> What can't be done is checking that the 'filelist' argument is
> correct, you have to make sure it's a "good" pointer (i.e. either
> NULL or pointing to allocated memory) by other means.
>
Hi Jens,
Okay, thank you, i extended my function by including this:
/* Check that path argument isn't a NULL pointer */
if ( !path ){
syslog( LOG_NOTICE, "nlog: 'path' argument is NULL in call of
getdir()" );
return -1;
}
/* Check that 'path' is ok (take into account the possibility that
'path' could be an empty string) */
if ( ! *path || path[ ( path_len =3D strlen( path ) ) - 1 ] !=3D '/' ){
syslog( LOG_NOTICE, "nlog: 'path' doesn't end in '/' in call of
getdir()" );
return -1;
}
before the opendir() call. But again, no messages appearing in syslog
but
this is what I'm geeting with strace:
[pid 21467] gettimeofday({1263839583, 94414}, NULL) =3D 0
[pid 21467] nanosleep({0, 100000000}, <unfinished ...>
[pid 21463] stat("/usr/share/NovaxTSP/", {st_mode=3DS_IFDIR|0755,
st_size=3D1024, ...}) =3D 0
[pid 21463] open("/usr/share/NovaxTSP/", O_RDONLY) =3D 15
[pid 21463] fcntl(15, F_SETFD, FD_CLOEXEC) =3D 0
[pid 21463] getdents(15, /* 13 entries */, 3933) =3D 308
[pid 21463] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
Process 21463 detached
[pid 21468] <... read resumed> 0xbe7ff918, 1024) =3D ? ERESTARTSYS (To
be restarted)
[pid 21464] <... accept resumed> 0xbefffb88, [16]) =3D ? ERESTARTSYS (To
be restarted)
[pid 21446] <... nanosleep resumed> {6, 572410750}) =3D ?
ERESTART_RESTARTBLOCK (To be restarted)
[pid 21493] <... recv resumed> 0xbe5ffcff, 1, 0) =3D ? ERESTARTSYS (To
be restarted)
[pid 21465] <... mq_timedreceive resumed> "\210\17\6\10", 4,
-1092616900, NULL) =3D ? ERESTARTSYS (To be restarted)
[pid 21466] <... mq_timedreceive resumed> "\1\1\17\0y
\0\0\0T0001\0\0\0", 16, 0, NULL) =3D ? ERESTARTSYS (To be restarted)
[pid 21462] <... poll resumed> ) =3D -1 EINTR (Interrupted system
call)
[pid 21467] <... nanosleep resumed> NULL) =3D ? ERESTART_RESTARTBLOCK
(To be restarted)
[pid 21462] +++ killed by SIGKILL +++
|
|
0
|
|
|
|
Reply
|
cerr
|
1/18/2010 6:35:02 PM
|
|
cerr <ron.eggler@gmail.com> wrote:
> before the opendir() call. But again, no messages appearing in syslog
> but
> this is what I'm geeting with strace:
> [pid 21467] gettimeofday({1263839583, 94414}, NULL) = 0
> [pid 21467] nanosleep({0, 100000000}, <unfinished ...>
> [pid 21463] stat("/usr/share/NovaxTSP/", {st_mode=S_IFDIR|0755,
> st_size=1024, ...}) = 0
> [pid 21463] open("/usr/share/NovaxTSP/", O_RDONLY) = 15
> [pid 21463] fcntl(15, F_SETFD, FD_CLOEXEC) = 0
> [pid 21463] getdents(15, /* 13 entries */, 3933) = 308
> [pid 21463] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
Lets assume that this really is from the getdir() function.
Then there are two possibilitues:
a) the 'filelist' argument isn't a pointer to memory obtailed
from malloc() or realloc() (or points to memory already
released) or NULL or
b) you have some memory corruption going on somewhere else in
your program that leads to some important internal data
structures being overwritten.
As Barry Margolin pointed out the place where a segmentation
fault occurs is very often seems to be completely unrelated
to where the the actual problem is in the program. It's not
uncommon to have calls of very well tested functions like
printf() or malloc() etc. fail with a segmentation fault
when at some place a few thousand lines away in the program
one of their internal data areas got overwritten accidentally.
So, concentrating on this function alone doesn't make too much
sense. The only think you can do is a careful code review of
the whole program or, if it's possible on your platform, to
use a memory debugger like valgrind. Sorry, but there are no
magic bullets, segmentation faults can be among the hardest
to find bugs.
If you want to know exactly where in the program the SEGFAULT
happens and you can't use a debugger you should add lots of
extra fprintf()'s to stderr (since sterr is unbuffered and
thus there is less danger of its output getting lost in the
aftermath of the SEGFAULT) that tell you which lines of the
function where executed before it happened. But I fear that
won't help too much since I guess the segmentation fault
happens somewhere in one of the libc functions you call,
which won't tell you much about the actual reason.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/18/2010 8:25:07 PM
|
|
On Jan 18, 12:25=A0pm, j...@toerring.de (Jens Thoms Toerring) wrote:
> cerr <ron.egg...@gmail.com> wrote:
> > before the opendir() call. But again, no messages appearing in syslog
> > but
> > this is what I'm geeting with strace:
> > [pid 21467] gettimeofday({1263839583, 94414}, NULL) =3D 0
> > [pid 21467] nanosleep({0, 100000000}, =A0<unfinished ...>
> > [pid 21463] stat("/usr/share/NovaxTSP/", {st_mode=3DS_IFDIR|0755,
> > st_size=3D1024, ...}) =3D 0
> > [pid 21463] open("/usr/share/NovaxTSP/", O_RDONLY) =3D 15
> > [pid 21463] fcntl(15, F_SETFD, FD_CLOEXEC) =3D 0
> > [pid 21463] getdents(15, /* 13 entries */, 3933) =3D 308
> > [pid 21463] --- SIGSEGV (Segmentation fault) @ 0 (0) ---
>
> Lets assume that this really is from the getdir() function.
> Then there are two possibilitues:
>
> a) the 'filelist' argument isn't a pointer to memory obtailed
> =A0 =A0from malloc() or realloc() (or points to memory already
> =A0 =A0released) or NULL or
> b) you have some memory corruption going on somewhere else in
> =A0 =A0your program that leads to some important internal data
> =A0 =A0structures being overwritten.
>
> As Barry Margolin pointed out the place where a segmentation
> fault occurs is very often seems to be completely unrelated
> to where the the actual problem is in the program. It's not
> uncommon to have calls of very well tested functions like
> printf() or malloc() etc. fail with a segmentation fault
> when at some place a few thousand lines away in the program
> one of their internal data areas got overwritten accidentally.
>
> So, concentrating on this function alone doesn't make too much
> sense. The only think you can do is a careful code review of
> the whole program or, if it's possible on your platform, to
> use a memory debugger like valgrind. Sorry, but there are no
> magic bullets, segmentation faults can be among the hardest
> to find bugs.
>
> If you want to know exactly where in the program the SEGFAULT
> happens and you can't use a debugger you should add lots of
> extra fprintf()'s to stderr (since sterr is unbuffered and
> thus there is less danger of its output getting lost in the
> aftermath of the SEGFAULT) that tell you which lines of the
> function where executed before it happened. But I fear that
> won't help too much since I guess the segmentation fault
> happens somewhere in one of the libc functions you call,
> which won't tell you much about the actual reason.
Okay, yay...alright...well what I have done is, I commented out that
additional module that i wrote for this piece of software and now this
application seems to be running fine. I don't have valgrind handy just
now as i need to spend some time first to get it compiled on my
target platform...
Any how the software looks like this:
- listen for connection
- receive data
- react upon parsing
- log received string
this are roughly the threads going on parallel.
What i did was, i rewrote the logging algorithm.
Before it just plainly wrote to syslog-ng with a defined
remote target (central server). I included custom TCP connection
receiving a layer 7 acknowledge upon delivery of string.
If for some reason this was unsuccesfull, i write the string into a
"log_record" file that gets found using above function and gets sent
to a log_record server but via a different TCP connection.
commenting out my push() function that pushes the logs onto my
array of char*s, resolves the SIGSEGV issue.
Would I be able to clearly tell where my SIGSEGV happens with
valgrind?
--
Thanks!
roN
|
|
0
|
|
|
|
Reply
|
cerr
|
1/18/2010 9:15:28 PM
|
|
cerr <ron.eggler@gmail.com> wrote:
> Okay, yay...alright...well what I have done is, I commented out that
> additional module that i wrote for this piece of software and now this
> application seems to be running fine.
Be careful, just because you don't get a segmentation fault
doesn't mean the original reason has gone, it just tells that
the point where the problems consequences become obvious now
isn't reached anymore.
> I don't have valgrind handy just
> now as i need to spend some time first to get it compiled on my
> target platform...
> Any how the software looks like this:
> - listen for connection
> - receive data
> - react upon parsing
> - log received string
> this are roughly the threads going on parallel.
> What i did was, i rewrote the logging algorithm.
> Before it just plainly wrote to syslog-ng with a defined
> remote target (central server). I included custom TCP connection
> receiving a layer 7 acknowledge upon delivery of string.
> If for some reason this was unsuccesfull, i write the string into a
> "log_record" file that gets found using above function and gets sent
> to a log_record server but via a different TCP connection.
> commenting out my push() function that pushes the logs onto my
> array of char*s, resolves the SIGSEGV issue.
That's a "high level" description of what you're doing, but
segmentation fault are something rather "low level" - you f*ck
up in a single place by doing something wrong with a pointer
and sometime later everything goes boom. Without seeing _all_
your code it's impossible to tell where things go wrong.
> Would I be able to clearly tell where my SIGSEGV happens with
> valgrind?
If you know what to look for valgrind can be very useful. But
it's not going to tell you in a single line "The assignment of
'x' to 'y' in line 42 in 'abc.c' will result in a segmentation
fault". All it can do is point out places where things look a
a bit fishy, and you still have to figure out what's a real
problem and what is ok (there are often a lot of warnings, some
of them not really useful and a few that you should take very
serious). So valgrind (or some other menory debugger) isn't a
silver bullet, it just can help you pinpoint where things might
be going wrong. And it only can tell you about problems in the
execution path that has really been taken when running the pro-
gram - thus if there's a segmentation fault that only happens
under obscure conditions you're unable to reproduce then it
won't be able to tell you about that (it doesn't check "the
program" as such but logs a lot of information while the pro-
gram is run). But then this is often a big help when just
looking at the code for a number of days doesn't work... So
it's a tool that can be very useful but which needs some
getting used to (i.e. it requires taking a bit of time to
understand what it can do and how to interpret what it tells
you).
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
|
|
0
|
|
|
|
Reply
|
jt
|
1/19/2010 1:43:53 AM
|
|
> > Would I be able to clearly tell where my SIGSEGV happens with
> > valgrind?
>
> If you know what to look for valgrind can be very useful. But
> it's not going to tell you in a single line "The assignment of
> 'x' to 'y' in line 42 in 'abc.c' will result in a segmentation
> fault". All it can do is point out places where things look a
> a bit fishy, and you still have to figure out what's a real
> problem and what is ok (there are often a lot of warnings, some
> of them not really useful and a few that you should take very
> serious). So valgrind (or some other menory debugger) isn't a
> silver bullet, it just can help you pinpoint where things might
> be going wrong. And it only can tell you about problems in the
> execution path that has really been taken when running the pro-
> gram - thus if there's a segmentation fault that only happens
> under obscure conditions you're unable to reproduce then it
> won't be able to tell you about that (it doesn't check "the
> program" as such but logs a lot of information while the pro-
> gram is run). But then this is often a big help when just
> looking at the code for a number of days doesn't work... So
> it's a tool that can be very useful but which needs some
> getting used to (i.e. it requires taking a bit of time to
> understand what it can do and how to interpret what it tells
> you).
Uhm .... okay.... I'm spending some time trying tio get it compiled. I
however would like to paste the function that i use to send off the
files collected with my getdir() function from above and hope that
someone can spend a little time looking through it...:
I call this function as follows:
SendLogFile(&list, files);
where files is a local integer holding the return value from my getdir
() function and list is a global "char **list;" that's been
initialized with NULL before it gets passed to getdir() like:
list=NULL;
now my send function.
LogServer_glob is a global "char* LogServer_glob;" defined with a
value like LogServer_glob=LogServer; where LogServer is a char*
argument in my init function.
int SendLogFile(char ***filelist, int items)
{
/**
* Function trys to establish connection to NEMS to send off the
log_record file saved in /usr/share/NovaxTSP/
* containing log messages that weren't sent succesfully to NEMS
in "real time"
*/
int port = 16003;
int rec_sock=-1;
int read_fd;
struct stat stat_buf;
int retval = 0;
off_t offset = 0;
int timeout=0;
if (items <= 0){
//syslog(LOG_NOTICE,"No log_records to send");
return -1;
}
//syslog(LOG_NOTICE,"DEBUG: before connecttoserver()");
rec_sock=connecttoserver(&LogServer_glob,port);
//syslog(LOG_NOTICE,"DEBUG: after connecttoserver() - SendLogFile");
if (rec_sock>=0) { // if connection opened
succesfully..
send(rec_sock, "LOG", 3, 0); // ...send command to go in
"LOG mode"
while(--items>=0) { // loop through all the items in
filelist
printf("sending %s\n",(*filelist)[items]);
syslog(LOG_NOTICE, "nlog: sending %s",(*filelist)
[items]);
do {
//open the log record file
read_fd = open((*filelist)[items], O_RDONLY);
//get the update file size
fstat(read_fd, &stat_buf);
retval =
sendfile(rec_sock, read_fd, &offset,
stat_buf.st_size);
if (retval == -1){
syslog(LOG_NOTICE, "nlog: Sending recorded log
file '%s' failed! Err: %s", (*filelist)[items],strerror(errno));
}
close(read_fd);
timeout++;
} while (retval == -1 && timeout < 50);
if (retval !=-1 && timeout < 50 ) { // delete the log record
if it got sent properly
printf("purging %s\n",(*filelist)[items]);
if (remove((*filelist)[items]))
syslog(LOG_NOTICE, "nlog: Error deleting %s",(*filelist)
[items]);
//else
//syslog(LOG_NOTICE, "nlog: Purged %s",(*filelist)[items]);
}
else
syslog(LOG_NOTICE, "nlog: can not purge %s",(*filelist)[items]);
free((*filelist)[items]);
}
free((*filelist));
if (rec_sock >= 0 ){
shutdown(rec_sock, SHUT_RDWR);
close(rec_sock);
}
}
else {
return -1;
}
return 1;
}
//-------------------------------------------------------
I made this logger file and its header available at
https://www.wuala.com/reggler/data/Novax/public?key=8snkpJJ9xvKv
that will probably be easier to look at things...
Thanks a lot to everyone spending time on that!
|
|
0
|
|
|
|
Reply
|
cerr
|
1/19/2010 5:21:00 PM
|
|
On Jan 19, 9:21=A0am, cerr <ron.egg...@gmail.com> wrote:
> > > Would I be able to clearly tell where my SIGSEGV happens with
> > > valgrind?
>
> > If you know what to look for valgrind can be very useful. But
> > it's not going to tell you in a single line "The assignment of
> > 'x' to 'y' in line 42 in 'abc.c' will result in a segmentation
> > fault". All it can do is point out places where things look a
> > a bit fishy, and you still have to figure out what's a real
> > problem and what is ok (there are often a lot of warnings, some
> > of them not really useful and a few that you should take very
> > serious). So valgrind (or some other menory debugger) isn't a
> > silver bullet, it just can help you pinpoint where things might
> > be going wrong. And it only can tell you about problems in the
> > execution path that has really been taken when running the pro-
> > gram - thus if there's a segmentation fault that only happens
> > under obscure conditions you're unable to reproduce then it
> > won't be able to tell you about that (it doesn't check "the
> > program" as such but logs a lot of information while the pro-
> > gram is run). But then this is often a big help when just
> > looking at the code for a number of days doesn't work... So
> > it's a tool that can be very useful but which needs some
> > getting used to (i.e. it requires taking a bit of time to
> > understand what it can do and how to interpret what it tells
> > you).
>
> Uhm .... okay.... I'm spending some time trying tio get it compiled. I
> however would like to paste the function that i use to send off the
> files collected with my getdir() function from above and hope that
> someone can spend a little time looking through it...:
> I call this function as follows:
> SendLogFile(&list, files);
> where files is a local integer holding the return value from my getdir
> () function and list is a global "char **list;" that's been
> initialized with NULL before it gets passed to getdir() like:
> list=3DNULL;
> now my send function.
> LogServer_glob is a global "char* LogServer_glob;" defined with a
> value like LogServer_glob=3DLogServer; where LogServer is a char*
> argument in my init function.
> int SendLogFile(char ***filelist, int items)
> {
> =A0 =A0 /**
> =A0 =A0 =A0* Function trys to establish connection to NEMS to send off th=
e
> log_record file saved in /usr/share/NovaxTSP/
> =A0 =A0 =A0* containing log messages that weren't sent succesfully to NEM=
S
> in "real time"
> =A0 =A0 =A0*/
> =A0 =A0 int port =3D 16003;
> =A0 =A0 int rec_sock=3D-1;
> =A0 =A0 int read_fd;
> =A0 =A0 struct stat stat_buf;
> =A0 =A0 int retval =3D 0;
> =A0 =A0 off_t offset =3D 0;
> =A0 =A0 int timeout=3D0;
>
> =A0 =A0 if (items <=3D 0){
> =A0 =A0 =A0 //syslog(LOG_NOTICE,"No log_records to send");
> =A0 =A0 =A0 return -1;
> =A0 =A0 }
> =A0 =A0 =A0 =A0 //syslog(LOG_NOTICE,"DEBUG: before connecttoserver()");
> =A0 =A0 =A0 =A0 rec_sock=3Dconnecttoserver(&LogServer_glob,port);
> =A0 =A0 =A0 =A0 //syslog(LOG_NOTICE,"DEBUG: after connecttoserver() - Sen=
dLogFile");
> =A0 =A0 =A0 =A0 if (rec_sock>=3D0) { =A0 =A0 =A0 =A0 // if connection ope=
ned
> succesfully..
> =A0 =A0 =A0 =A0 =A0 =A0 send(rec_sock, "LOG", 3, 0); =A0// ...send comman=
d to go in
> "LOG mode"
> =A0 =A0 =A0 =A0 =A0 =A0 while(--items>=3D0) { // loop through all the ite=
ms in
> filelist
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf("sending %s\n",(*filelist)[items])=
;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog: sending %s",(*f=
ilelist)
> [items]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 do {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 //open the log record file
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read_fd =3D open((*filelist)[item=
s], O_RDONLY);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 //get the update file size
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fstat(read_fd, &stat_buf);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sendfile(rec_sock, read_f=
d, &offset,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0stat_b=
uf.st_size);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (retval =3D=3D -1){
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog:=
Sending recorded log
> file '%s' failed! Err: %s", (*filelist)[items],strerror(errno));
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 close(read_fd);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 timeout++;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } while (retval =3D=3D -1 && timeout < 50=
);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (retval !=3D-1 && timeout < 50 ) { =A0=
=A0 =A0 // delete the log record
> if it got sent properly
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf("purging %s\n",(*filelist)[ite=
ms]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (remove((*filelist)[items]))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog: Error d=
eleting %s",(*filelist)
> [items]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 //else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 //syslog(LOG_NOTICE, "nlog: Purge=
d %s",(*filelist)[items]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 syslog(LOG_NOTICE, "nlog: can not pur=
ge %s",(*filelist)[items]);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free((*filelist)[items]);
> =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 =A0 =A0 free((*filelist));
> =A0 =A0 =A0 =A0 =A0 =A0 if (rec_sock >=3D 0 ){
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 shutdown(rec_sock, SHUT_RDWR);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 close(rec_sock);
> =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 else {
> =A0 =A0 =A0 =A0 =A0 return -1;
> =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 return 1;}
>
> //-------------------------------------------------------
I have figured stuff out! Thanks for everyone's patience and help! I
got to take a lot out of it!
Thanks,
roN :)
|
|
0
|
|
|
|
Reply
|
cerr
|
1/19/2010 9:35:39 PM
|
|
On Tue, 19 Jan 2010 09:21:00 -0800, cerr wrote:
>> > Would I be able to clearly tell where my SIGSEGV happens with
>> > valgrind?
>>
>> If you know what to look for valgrind can be very useful. But it's not
>> going to tell you in a single line "The assignment of 'x' to 'y' in
>> line 42 in 'abc.c' will result in a segmentation fault". All it can do
>> is point out places where things look a a bit fishy, and you still have
>> to figure out what's a real problem and what is ok (there are often a
>> lot of warnings, some of them not really useful and a few that you
>> should take very serious). So valgrind (or some other menory debugger)
>> isn't a silver bullet, it just can help you pinpoint where things might
>> be going wrong. And it only can tell you about problems in the
>> execution path that has really been taken when running the pro- gram -
>> thus if there's a segmentation fault that only happens under obscure
>> conditions you're unable to reproduce then it won't be able to tell you
>> about that (it doesn't check "the program" as such but logs a lot of
>> information while the pro- gram is run). But then this is often a big
>> help when just looking at the code for a number of days doesn't work...
>> So it's a tool that can be very useful but which needs some getting
>> used to (i.e. it requires taking a bit of time to understand what it
>> can do and how to interpret what it tells you).
> Uhm .... okay.... I'm spending some time trying tio get it compiled. I
> however would like to paste the function that i use to send off the
> files collected with my getdir() function from above and hope that
> someone can spend a little time looking through it...: I call this
> function as follows:
> SendLogFile(&list, files);
> where files is a local integer holding the return value from my getdir
> () function and list is a global "char **list;" that's been initialized
> with NULL before it gets passed to getdir() like: list=NULL;
> now my send function.
> LogServer_glob is a global "char* LogServer_glob;" defined with a value
> like LogServer_glob=LogServer; where LogServer is a char* argument in my
> init function.
> int SendLogFile(char ***filelist, int items) {
> /**
> * Function trys to establish connection to NEMS to send off the
> log_record file saved in /usr/share/NovaxTSP/
> * containing log messages that weren't sent succesfully to NEMS
> in "real time"
> */
> int port = 16003;
> int rec_sock=-1;
> int read_fd;
> struct stat stat_buf;
> int retval = 0;
> off_t offset = 0;
> int timeout=0;
>
>
> if (items <= 0){
> //syslog(LOG_NOTICE,"No log_records to send"); return -1;
> }
> //syslog(LOG_NOTICE,"DEBUG: before connecttoserver()");
> rec_sock=connecttoserver(&LogServer_glob,port);
> //syslog(LOG_NOTICE,"DEBUG: after connecttoserver() - SendLogFile");
> if (rec_sock>=0) { // if connection opened
> succesfully..
In most cases it is easier to check for -1 and do an early return.
> send(rec_sock, "LOG", 3, 0); // ...send command to go in
> "LOG mode"
> while(--items>=0) { // loop through all the items in
> filelist
> printf("sending %s\n",(*filelist)[items]);
> syslog(LOG_NOTICE, "nlog: sending %s",(*filelist)
> [items]);
> do {
> //open the log record file
> read_fd = open((*filelist)[items], O_RDONLY); //get
> the update file size
Check the return value.
> fstat(read_fd, &stat_buf);
Check the return value.
> retval =
> sendfile(rec_sock, read_fd, &offset,
> stat_buf.st_size);
You forgot to set offset when opening a new file.
It is initialized to zero only for the first file.
> if (retval == -1){
> syslog(LOG_NOTICE, "nlog: Sending recorded log
> file '%s' failed! Err: %s", (*filelist)[items],strerror(errno));
> }
Check the return value AND check errno. Act appropriately.
> close(read_fd);
Why would you want to close and reopen the same file over and over again ?
> timeout++;
> } while (retval == -1 && timeout < 50);
> if (retval !=-1 && timeout < 50 ) { // delete the log record
> if it got sent properly
> printf("purging %s\n",(*filelist)[items]); if
> (remove((*filelist)[items]))
> syslog(LOG_NOTICE, "nlog: Error deleting %s",(*filelist)
> [items]);
> //else
> //syslog(LOG_NOTICE, "nlog: Purged %s",(*filelist)[items]);
> }
> else
> syslog(LOG_NOTICE, "nlog: can not purge %s",(*filelist)[items]);
> free((*filelist)[items]);
> }
> free((*filelist));
> if (rec_sock >= 0 ){
> shutdown(rec_sock, SHUT_RDWR);
You must have a very good reason to use shutdown().
In most cases close() is sufficient.
> close(rec_sock);
> }
> }
> else {
> return -1;
> }
> return 1;
IMHO this is an ugly tail, avoidable by leaving the loop early.
> }
> //------------------------------------------------------- I made this
> logger file and its header available at
> https://www.wuala.com/reggler/data/Novax/public?key=8snkpJJ9xvKv that
Unreachable without registration.
> will probably be easier to look at things... Thanks a lot to everyone
> spending time on that!
HTH,
AvK
|
|
0
|
|
|
|
Reply
|
Moi
|
1/20/2010 10:44:31 AM
|
|
|
22 Replies
350 Views
(page loaded in 0.197 seconds)
|