Thread: I'm out of ideas...

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    I'm out of ideas...

    I've been trying to diagnose why my app stopped finding itself in /proc and now I've run out of ideas on what the cause is (cause I fixed every problem I found besides this one) so now I'm asking peops to have a look at the last code executed before the loop dies on the 1st attempt.
    Code:
    	while ( (ent = readdir(glance->dir)) ) {
    		if ( ent->d_name[0] < '0' || ent->d_name[0] > '9' )
    			continue;
    		(void)sscanf( ent->d_name, "%d", &entryId );
    		notice->ownerId = entryId;
    		while ( proc_notice_info( err, notice->ownerId, notice ) )
    		{
    			if ( notice->ownerId == glance->underId )
    				return proc_notice_info( err, entryId, notice );
    			if ( notice->ownerId <= 0 )
    				break;
    		}
    	}
    	if ( err ) *err = EXIT_SUCCESS;
    	proc_glance_shut( glance );
    	return NULL;
    ...
    proc_notice_t* proc_notice_info(
    	int *err, int pid, proc_notice_t *notice )
    {
    	int fd;
    	char path[256] = {0};
    	space_t *full, *key, *val, *name;
    	kvpair_t *kvpair;
    	int ret;
    	char *txt, *k, *v;
    	intptr_t size;
    	if ( !notice ) {
    		if ( err ) *err = EDESTADDRREQ;
    		ERRMSG( EDESTADDRREQ, "notice was NULL" );
    		return NULL;
    	}
    	kvpair = &(notice->kvpair);
    	name = &(notice->name);
    	full = &(kvpair->full);
    	key = &(kvpair->key);
    	val = &(kvpair->val);
    	memset( name->block, 0, name->given );
    	memset( full->block, 0, full->given );
    	memset( key->block, 0, key->given );
    	memset( val->block, 0, val->given );
    	notice->ownerId = -1;
    	notice->entryId = pid;
    	sprintf( path, "/proc/%d/status", pid );
    	/* Implements a fallback looped read call in the event lseek gleans
    	 * nothing */
    	if ( !(size = file_get_size( &ret, path )) ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't get status size" );
    		return NULL;
    	}
    	if ( (fd = open(path,O_RDONLY)) < 0 ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't open status file" );
    		printf( "File '%s'\n", path );
    		return NULL;
    	}
    	if ( !more_space( &ret, full, size )) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory to read into" );
    		fprintf( stderr, "Wanted %zu bytes\n", size );
    		close(fd);
    		return NULL;
    	}
    	if ( !gasp_read(fd, full->block, full->given) ) {
    		close(fd);
    		ret = ENODATA;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't read the status file" );
    		return NULL;
    	}
    	/* No longer need the file opened since we have everything */
    	close(fd);
    	if ( (ret = change_kvpair(
    		kvpair, full->given,
    		full->given, full->given, 1 )) != EXIT_SUCCESS ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory for key/val pair" );
    		return NULL;
    	}
    	/* Ensure we have enough space for the name */
    	if ( !more_space( &ret, name, full->given ) ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory for name");
    		return NULL;
    	}
    	txt = strstr( full->block, "\n" );
    	if ( !txt ) {
    		ret = ENOSYS;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Don't know how to handle the status file" );
    		return NULL;
    	}
    	/* Don't want strlen to count through everything */
    	*txt = 0;
    	/* Find the start of the name given */
    	v = strstr( (k = full->block), "\t" );
    	if ( !v ) {
    		ret = ENODATA;
    		if ( *err ) *err = ret;
    		ERRMSG( ret, "Couldn't find character '\t' in read text");
    		(void)fprintf(stderr,"read '%s'\n", full->block );
    		return NULL;
    	}
    	++v;
    	/* Fill name with the name given */
    	memcpy( name->block, v, strlen(v) );
    	/* Restore ability for strstr to see next character */
    	*txt = '\n';
    	while ( (k = txt = strstr( txt, "\n" )) ) {
    		*k = 0; ++k;
    		v = strstr( k, "\t" );
    		*v = 0;
    		/* This is currently the only value we care about besides the
    		 * name */
    		if ( strcmp( k, "PPid:" ) == 0 ) break;
    		*v = '\t';
    		*(--k) = '\n';
    		++txt;
    	}
    	if ( !txt ) {
    		ret = ENOENT;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't locate ownerId" );
    		return NULL;
    	}
    	/* Just in case we decide to take more parameters */
    	*v = '\t';
    	sscanf( txt, "%d",	&(notice->ownerId) );
    	if ( err ) *err = EXIT_SUCCESS;
    	return notice;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > while ( (ent = readdir(glance->dir)) )
    So which dir are you reading here?

    My guess is /proc is changed for some reason (maybe a process got added or removed), and that invalidated your directory iterator before you got to the end.

    Maybe read all the pids in one loop, quickly, with no I/O.
    Then use another loop to read all those pids, or at least verify that itself is in the list.


    I generally find most of your code to be unreadable, possibly because it comes across as a wall of text.
    A few blank lines between each block of code wouldn't go amiss.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Salem View Post
    > while ( (ent = readdir(glance->dir)) )
    So which dir are you reading here?

    My guess is /proc is changed for some reason (maybe a process got added or removed), and that invalidated your directory iterator before you got to the end.

    Maybe read all the pids in one loop, quickly, with no I/O.
    Then use another loop to read all those pids, or at least verify that itself is in the list.


    I generally find most of your code to be unreadable, possibly because it comes across as a wall of text.
    A few blank lines between each block of code wouldn't go amiss.
    Ah that's what peops were refering to when they say unreadable, I'll try to fix that then, as for the invalidated bit I guess that makes sense I'll switch to an ID list then, still fits with the glance concept after all

  4. #4
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Still running into the same issue, somehow every ID I iterate through is 0, I'll post the change here plus the function that fills the list, tried making it more "readable" though if I'm honest I liked it better before where I didn't have to scroll as much.
    Code:
    for ( ; glance->process < glance->idNodes.count; glance->process++ )
    	{
    		notice->ownerId = *(
    			((int*)(glance->idNodes.space.block)) + glance->process);
    
    		while ( proc_notice_info( err, notice->ownerId, notice ) )
    		{
    			if ( notice->ownerId == glance->underId )
    				return proc_notice_info( err, entryId, notice );
    			if ( notice->ownerId <= 0 )
    				break;
    		}
    	}
    
    	if ( err ) *err = EXIT_SUCCESS;
    	proc_glance_shut( glance );
    	return NULL;
    }
    
    proc_notice_t*
    	proc_glance_open( int *err, proc_glance_t *glance, int underId ) {
    	int ret = errno = EXIT_SUCCESS;
    	DIR *dir;
    	struct dirent *ent;
    	node_t i = 0;
    	if ( !glance ) {
    		if ( err ) *err = EDESTADDRREQ;
    		ERRMSG( EDESTADDRREQ, "glance was NULL" );
    		return NULL;
    	}
    	(void)memset( glance, 0, sizeof(proc_glance_t) );
    	glance->underId = underId;
    	if ( more_nodes( int, &ret, &(glance->idNodes), 2000 ) ) {
    		if ( (dir = opendir("/proc")) ) {
    			
    			while ( (ent = readdir( dir )) ) {
    				if ( ent->d_name[0] < '0' && ent->d_name[0] > '9' )
    					continue;
    
    				if ( (ret = add_node(
    					&(glance->idNodes), &i, sizeof(int) ))
    					!= EXIT_SUCCESS )
    					break;
    
    				sscanf( ent->d_name, "%d",
    					((int*)(glance->idNodes.space.block)) + i );
    			}
    			closedir(dir);
    			
    			if ( glance->idNodes.count )
    				return proc_notice_next( err, glance );
    		}
    	}
    	ret = ( errno != EXIT_SUCCESS ) ? errno : EXIT_FAILURE;
    	if ( err ) *err = ret;
    	ERRMSG( ret, "glance->dir was NULL" );
    	return NULL;
    }
    ...
    proc_notice_t* proc_notice_info(
    	int *err, int pid, proc_notice_t *notice )
    {
    	int fd;
    	char path[256] = {0};
    	space_t *full, *key, *val, *name;
    	kvpair_t *kvpair;
    	int ret;
    	char *txt, *k, *v;
    	intptr_t size;
    	
    	if ( !notice ) {
    		if ( err ) *err = EDESTADDRREQ;
    		ERRMSG( EDESTADDRREQ, "notice was NULL" );
    		return NULL;
    	}
    	
    	kvpair = &(notice->kvpair);
    	name = &(notice->name);
    	full = &(kvpair->full);
    	key = &(kvpair->key);
    	val = &(kvpair->val);
    	
    	memset( name->block, 0, name->given );
    	memset( full->block, 0, full->given );
    	memset( key->block, 0, key->given );
    	memset( val->block, 0, val->given );
    	
    	notice->ownerId = -1;
    	notice->entryId = pid;
    	sprintf( path, "/proc/%d/status", pid );
    	
    	/* Implements a fallback looped read call in the event lseek gleans
    	 * nothing */
    	if ( !(size = file_get_size( &ret, path )) ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't get status size" );
    		return NULL;
    	}
    	
    	if ( (fd = open(path,O_RDONLY)) < 0 ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't open status file" );
    		printf( "File '%s'\n", path );
    		return NULL;
    	}
    	
    	if ( !more_space( &ret, full, size )) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory to read into" );
    		fprintf( stderr, "Wanted %zu bytes\n", size );
    		close(fd);
    		return NULL;
    	}
    	
    	if ( !gasp_read(fd, full->block, full->given) ) {
    		close(fd);
    		ret = ENODATA;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't read the status file" );
    		return NULL;
    	}
    	
    	/* No longer need the file opened since we have everything */
    	close(fd);
    	if ( (ret = change_kvpair(
    		kvpair, full->given,
    		full->given, full->given, 1 )) != EXIT_SUCCESS ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory for key/val pair" );
    		return NULL;
    	}
    	
    	/* Ensure we have enough space for the name */
    	if ( !more_space( &ret, name, full->given ) ) {
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't allocate memory for name");
    		return NULL;
    	}
    	
    	txt = strstr( full->block, "\n" );
    	if ( !txt ) {
    		ret = ENOSYS;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Don't know how to handle the status file" );
    		return NULL;
    	}
    	
    	/* Don't want strlen to count through everything */
    	*txt = 0;
    	
    	/* Find the start of the name given */
    	v = strstr( (k = full->block), "\t" );
    	if ( !v ) {
    		ret = ENODATA;
    		if ( *err ) *err = ret;
    		ERRMSG( ret, "Couldn't find character '\t' in read text");
    		(void)fprintf(stderr,"read '%s'\n", full->block );
    		return NULL;
    	}
    	
    	/* We don't want to copy the tab character */
    	++v;
    	
    	/* Fill name with the name given */
    	memcpy( name->block, v, strlen(v) );
    	
    	/* Restore ability for strstr to see next character */
    	*txt = '\n';
    	
    	while ( (k = txt = strstr( txt, "\n" )) ) {
    		*k = 0; ++k;
    		v = strstr( k, "\t" );
    		*v = 0;
    		/* This is currently the only value we care about besides the
    		 * name */
    		if ( strcmp( k, "PPid:" ) == 0 ) break;
    		*v = '\t';
    		*(--k) = '\n';
    		++txt;
    	}
    	
    	if ( !txt ) {
    		ret = ENOENT;
    		if ( err ) *err = ret;
    		ERRMSG( ret, "Couldn't locate ownerId" );
    		return NULL;
    	}
    	
    	/* Just in case we decide to take more parameters */
    	*v = '\t';
    	sscanf( txt, "%d",	&(notice->ownerId) );
    	if ( err ) *err = EXIT_SUCCESS;
    	return notice;
    }

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Whoops just realised I forgot to change the && to on this line:
    Code:
    if ( ent->d_name[0] < '0' && ent->d_name[0] > '9' )
    	continue;
    Didn't resolve my problem of not finding itself but did resolve the list of 0s I saw

  6. #6
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    while (ent = readdir(glance->dir))
    does this loop ever exit ?

    if ( !(size = file_get_size( &ret, path )) )
    if (dir = opendir("/proc"))
    take a look at this: Operators in C
    Last edited by Structure; 01-28-2020 at 03:27 PM.
    "without goto we would be wtf'd"

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Structure
    does this loop ever exit ?
    Yes, because at some point readdir will return a null pointer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    Code:
    while (ent = readdir(glance->dir)) {}
    does this loop ever exit ?

    Yes, because at some point readdir will return a null pointer.
    I'm out of ideas...-wtf-jpg
    "without goto we would be wtf'd"

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Structure
    take a look at this: Operators in C
    You might want to say what's wrong with awsdert's code such that taking a look at that webpage makes sense. I note that awsdert's code does suppress a common compiler warning associated with using such assignments within conditionals, i.e., by wrapping it in an extra pair of parentheses to signal that the assignment was deliberate rather than a typo for == whereas your paraphrase of awsdert's code omits those parentheses.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    wrapping it in an extra pair of parentheses to signal that the assignment was deliberate rather than a typo
    I'm out of ideas...-wtf2-jpg

    are you saying the compiler switches out the = with == ?

    You might want to say what's wrong with awsdert's code
    to see if 2 values are equal you would:
    Code:
    if ( a == b ) { };
    if a is equal to b it will run the block.
    Code:
    if ( a = b ) { };
    at this point you set a to b and you are no longer comparing.
    i believe it will always be true and run the block.

    i.e:
    Code:
    if ( !(size = file_get_size( &ret, path )) ){ };
    should never run the block since size will always be equal to the value you set it to.
    Last edited by Structure; 01-28-2020 at 03:56 PM.
    "without goto we would be wtf'd"

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    readdir is not part of standard C, but it is POSIX standard, so if you don't know how readdir works, it's pretty easy to find out because POSIX stuff tends to be online via web-based manual pages and such.

    Quote Originally Posted by Structure
    are you saying the compiler switches out the = with == ?
    No. The assignment is intentional. Comparing for equality would be a bug because those variables have not been set to an initial value at that point.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    The assignment is intentional
    Some things you guys do i can understand. Others i can't and most likely never will.
    What i can tell you is it obviously doesn't work the way it's being done.

    if ( !(size = file_get_size( &ret, path )) ) { };
    I would be shocked that block of code ever gets executed.
    Last edited by Structure; 01-28-2020 at 04:09 PM.
    "without goto we would be wtf'd"

  13. #13
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Oh wow, I watch a vid or 2 and come back to find my thread far busier than expected XD
    Glad to see at least 1 person understood the assignment was intentional though
    Still I wish I could figure out why my app can't find itself 😓

  14. #14
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Structure View Post
    Some things you guys do i can understand. Others i can't and most likely never will.
    What i can tell you is it obviously doesn't work the way it's being done.


    I would be shocked that block of code ever gets executed.
    Prepare to be shocked then... cause it does

  15. #15
    null pointer Structure's Avatar
    Join Date
    May 2019
    Posts
    338
    at some point readdir will return a null pointer.
    Code:
    #include <stdio.h>
    
    int main() {
        int a = 100, *b;
        if ( !(a = *b) ) {
            printf("interesting.");
        };
    };
    Code:
    if ( !(a = b) ) {  
      printf("fails.");
    };
    "without goto we would be wtf'd"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. in need of some ideas and help....HELP!!!!
    By ccar033 in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 04:58 AM
  2. help with ideas
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 05-02-2002, 11:21 PM
  3. Any Ideas?
    By brad123 in forum C Programming
    Replies: 4
    Last Post: 04-28-2002, 09:00 AM
  4. Ideas
    By GodLike in forum Game Programming
    Replies: 5
    Last Post: 04-16-2002, 01:57 PM
  5. ideas?
    By pode in forum C++ Programming
    Replies: 3
    Last Post: 02-04-2002, 04:13 PM

Tags for this Thread