[coldfire-gnu-discuss] systemcall select() seems to overwrite variables on the stack
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[coldfire-gnu-discuss] systemcall select() seems to overwrite variables on the stack



 Hello!

I recently came across a very annoying problem.
All this is happening with the latest version of the toolchain
(freescale-coldfire-m68k-linux-gnu-4.4-217.i686.rpm).

I have a multithreading application in which one thread simply calls select() in a loop for a single descriptor and then updates some pointers in case of a successful return. The problem now is: The first parameter to select seems to get destroyed in certain cases.
I have included the problematic code as an attachement.

The following happens: At the beginning of the thread, I declare the variable "nfds" and initialize it with (select_fd + 1). But just after the return of select() the variable has some useless value (see output). This "useless value" is always the same!
The code produces the following output:

...
ldi_dev.c  before select_fd=67 | nfds = 68
ldi_dev.c  before select_fd=67 | nfds = -2141341700
ldi_dev.c  select(): Invalid argument
ldi_dev.c  exiting mainloop

The problem didn't occur with the old toolchain (freescale-coldfire-m68k-linux-gnu-4.2-35.i686.rpm). The problem doesn't occur when compiling without the optimization flag (the problematic code gets compiled with -O2 by default).
The code works when using the poll() systemcall.

Since the variable "nfds" is only visible to this particular thread,
this cannot be a multithreading problem.
See the attached screenshot for ddd output.

Now what makes this even more confusing is, that the code seems to work when I uncomment the trace just after the call to select()... I was assuming it might be a libc problem, because I came across this mailinglist entry:
http://sources.redhat.com/ml/libc-alpha/2003-06/msg00030.html

I hope it's not a bug in the compiler. We updated to the latest version of the toolchain because we ran across some mutex related problems with the old version (it seems that sometimes threads don't get waken up when they were waiting for a mutex that was locked the moment they tried to acquire the lock).

Best regards,
Andreas Wehrmann

--
Dipl.-Ing. (FH) Andreas Wehrmann
Software Development
--------------------------------------------------------------
Center Communication Systems GmbH
A-1210 Wien, Ignaz-Köck-Straße 19
Sitz in Wien
FN 796 88p, Firmenbuchgericht Wien
www.centersystems.com

Tel.: +43 (0) 190 199 - 3616
Mobile: +43 (0) 664 884 75916
Fax: +43 (0) 190 199 - 2110
E-Mail: a.wehrmann@xxxxxxxxxxxxxxxxx

Attachment: value_change.jpg
Description: JPEG image

// thread main function
void *threadfunc(void *arg)
{
    struct ldi_stream *stream = (struct ldi_stream*) arg;
    struct pollfd evt;

    evt.fd = stream->sound_dev;
    evt.events = POLLIN;
    evt.revents = 0;

    // register this thread with PJ
    pj_status_t status = pj_thread_register(
        "ldi thread", 
        stream->thread_desc, 
        &stream->pj_thread);

    pj_assert(status == PJ_SUCCESS);

    // real loop on LDI
    int select_fd;
    select_fd = stream->sound_dev;
    int nfds = select_fd + 1;

    stream->run = 1;

// fake loop for PC version
// simulate the 20ms clock
#ifdef __i386
    while( stream->run )
    {
        usleep( 20 * 1000 );
        onFDReadable(stream, stream->sound_dev);

    }
    return NULL;
#endif

    TRACE_("entering mainloop");
    struct timeval timeout;
    fd_set rdfds;
    int retval = 0;
    
    while(stream->run)
    {
//         evt.fd = stream->sound_dev;
//         evt.events = POLLIN;
//         evt.revents = 0;
            timeout.tv_sec = 5;
            timeout.tv_usec = 0;
            
        FD_ZERO(&rdfds);
        FD_SET(select_fd, &rdfds);
        
        // wait on /dev/ldisnd
        TRACE_("before select_fd=%d | nfds = %d", select_fd, nfds );
        retval = select( nfds, &rdfds, NULL, NULL, &timeout);
//         TRACE_("after select_fd=%d | nfds = %d", select_fd, nfds );
//                 retval = poll( &evt, 1, 5000 );
        if (retval > 0)
        {
            if FD_ISSET(select_fd, &rdfds)
            {
               // handle data
            //
            //  SET_MODUL_IO3_v3;
                onFDReadable(stream, select_fd);
            //   CLR_MODUL_IO3_v3;
            }
            else
            {
                TRACE_("unhandled FD\n");
                stream->run = 0;
            }
        }
        else if (retval < 0)
        {
            PERROR("select()");
            stream->run = 0;
        }
    }

    TRACE_("exiting mainloop");
    return NULL;
}