LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   strace showing _exit() vs exit_group() (https://www.linuxquestions.org/questions/programming-9/strace-showing-_exit-vs-exit_group-4175535731/)

paulc4 03-04-2015 08:07 AM

strace showing _exit() vs exit_group()
 
Hi guys,

I'm struggling with the following program (sample.cpp):

Code:

#include <stdio.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include "MyLibrary.h"

void someDummyfunction()
{
        // Comment this out, and program finishes with exit_group(0)
        MyLibraryFunction(0, NULL, 0);
}

int main(int argc, char* argv[])
{

    // OR, comment this out, and the program finishes with exit_group(0)
        gtk_init( &argc, &argv );
    return (0);
}

MyLibrary is a .so that I recently created, and I'm trying to write a GTK enabled program that uses it. I have stripped this program down to just the above to demonstrate the problem I'm having.

When I run this program as shown above, the program 'hangs' -- meaning it runs, but never ends and returns back to the command prompt -- I have to Ctrl-C it. When I strace the program, the last thing it does is a _exit(0).

However, if I comment out either the call to gtk_init(), OR, comment out the reference to MyLibraryFunction() (note that it's simplying referencing the function, it does not call it). -- the program terminates fine. When I strace this variant, I see that the last thing it does it a exit_group(0).

Why the difference?

I've been using the library MyLibrary with non-gtk apps for a while now, and they seem to work fine (they all seem to end with a exit_group). Now MyLibrary is a fairly complicated library, and it too references a number of other libraries. One of these libraries is pthreads, as it does utilize multi-threading. However, I believe all of the threading stuff is 'dynamic' -- only created at runtime (which isn't happening as we are not even calling into it).

Anyways -- I believe the issue is somewhere in MyLibrary, but I was wondering if perhaps someone had some ideas of what to look for based on the _exit vs exit_group behavior I am seeing.

For reference, here is my makefile...

Code:

CXX=g++
INCLUDES=-I$(MYLIBRARY_INC)
LIBPATH=-L$(MYLIBRARY_LIB)
LIBS=-lMyLibrary
CFLAGS=-O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP $(DEFINES) $(INCLUDES)
LDFLAGS=

CFLAGS += `pkg-config --cflags gtk+-3.0 gmodule-2.0`
LDFLAGS += `pkg-config --libs gtk+-3.0 gmodule-2.0`

SRCFILES=sample.cpp
OBJFILES=$(SRCFILES:.cpp=.o)

all: sample

sample: $(OBJFILES)
        rm -f $@
        $(CXX) $(LIBPATH) -o $@ $^ $(LIBS) $(LDFLAGS)

.cpp.o:
        $(CXX) $(CFLAGS) $< -o $@

clean:
        rm -rf *.o
        rm -rf sample


Thanks
/Paul

NevemTeve 03-04-2015 09:09 AM

gtk_init might start additional process(es) or thread(s)
use flag -f when strace-ing

Note: I think you should add to your CPPFLAGS (or DEFINES in your case) Makefile-variable option -D_THREAD_SAFE

SoftSprocket 03-04-2015 09:34 AM

gtk_init calls exit when it fails. That's why you see the particular behavior. gtk_init_check won't call exit, it will return false. gtk_init_with_args does the same but has an error parameter that might help. It contains a message field.

paulc4 03-04-2015 10:42 AM

Thanks for the replies thus far.

NevemTeve --> I added the definition of the compile option _THREAD_SAFE as you suggested.

SoftSprocekt --> What you stated sounded promising, but alas, it is not my problem. Both gtk_init and gtk_init_check are returning fine (in the latter case, it returns TRUE). In fact if I put a printf just before the return (0), it prints fine. The _exit(0) is coming from the return(0) of main()??

my quest continues...

NevemTeve 03-04-2015 10:54 AM

gtk_init might start additional process(es) or thread(s)
use flag -f when strace-ing

paulc4 03-04-2015 11:24 AM

NevemTeve,

I had read your initial comment, but didn't respond to it -- sorry about that.

Yes, gtk_init might be creating some additional process(es) or thread(s), and I'm not calling any of the 'latter' gtk functions that might clean these up (such as gtk_main(). However, a more 'complete' gtk program is where I started when I discovered this error, using some simple and widly distributed gtk applications that did all of this stuff -- but my program continued to misbehave. I stripped it down to what you see here. Furthermore, if I comment our the reference to MyLibraryFunction, than the program runs fine; both gtk_init() and main() return as expected -- I get the exit_group that seems to be larger is scope (thread-wise).

I also tried using the -f option for strace. Here is what I see at the very end ...

Code:

8110  12:15:48 write(1, "Hello world\n", 12) = 12
8110  12:15:48 futex(0x7f8383805850, FUTEX_WAKE_PRIVATE, 2147483647) = 0
8110  12:15:48 _exit(0)                = ?
8111  12:15:52 <... poll resumed> )    = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
8111  12:15:52 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
8111  12:15:52 +++ killed by SIGINT +++
8112  12:15:52 +++ killed by SIGINT +++
8110  12:15:52 +++ killed by SIGINT +++

The "Hello world" write is a printf I added to main(), just before the return (0). The 'poll resumed' is the Ctrl+C I did to terminate the program.

Hmmm... that futex looks interesting...

NevemTeve 03-04-2015 11:47 AM

This suggest three processes (pid=8110,8111,8112)

paulc4 03-05-2015 07:27 AM

Quote:

Originally Posted by NevemTeve (Post 5326881)
This suggest three processes (pid=8110,8111,8112)

Yes, it certainly does. However, if I don't define the MyLibraryFunction, then it too will show three threads -- but will then do a exit_group() (as opposed to _exit()) and terminate properly.

With that stated however, I've done more experimentation, and my example program now looks as follows:

Code:

#include <stdio.h>
#include <pthread.h>
#include <gtk/gtk.h>

int main(int argc, char* argv[])
{

        if (! gtk_init_check( &argc, &argv ))
        {
                printf ("gtk_init_check Failed !!\n");
        }
       
        printf ("Hello world\n");

        pthread_exit(NULL);
        return (0);
}

And I've also simplified my makefile:

Code:

CXX=g++
INCLUDES=
LIBPATH=
DEFINES=-D_THREAD_SAFE
LIBS=-lpthread
CFLAGS=-O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP $(DEFINES) $(INCLUDES)
LDFLAGS=

CFLAGS += `pkg-config --cflags gtk+-3.0 gmodule-2.0`
LDFLAGS += `pkg-config --libs gtk+-3.0 gmodule-2.0`

SRCFILES=sample.cpp
OBJFILES=$(SRCFILES:.cpp=.o)

all: sample

sample: $(OBJFILES)
        rm -f $@
        $(CXX) $(LIBPATH) -o $@ $^ $(LIBS) $(LDFLAGS)

.cpp.o:
        $(CXX) $(CFLAGS) $< -o $@

clean:
        rm -rf *.o
        rm -rf sample

This program fails in the same way. Basically, if I do the pthread_exit() in main (as I understand I am supposed to do if I am using pthreads) -- then main will 'hang' on this operation if I had previously called gtk_init_check() (or gtk_init()).

Incidentally, I also went back to try my more complete variant of the gtk program (one that actually has a gtk_main()), and it too will hang up main() if I add a call to pthread_exit().

Thanks

pan64 03-05-2015 07:40 AM

the usual way is to use -pthread both for compiling and linking, otherwise there can be surprises (and do not use -lpthread). Probably the best thing is to use
Code:

CXX=g++ -pthread
and LIBS is not required. But I'm not really sure that will solve this issue.

NevemTeve 03-05-2015 07:47 AM

Well, I don't have gtk+-3.0; with gtk+2.0 it prints 'Hello world' and exits

end of strace log:
Code:

write(1, "Hello world\n", 12Hello world
)          = 12
futex(0xf6db9228, FUTEX_WAKE_PRIVATE, 2147483647) = 0
gettimeofday({1425563209, 687442}, NULL) = 0
gettimeofday({1425563209, 687520}, NULL) = 0
exit_group(0)                          = ?


pan64 03-05-2015 08:00 AM

oh yes, and your shared library should be compiled with -pthread too.

paulc4 03-05-2015 08:54 AM

Quote:

Originally Posted by NevemTeve (Post 5327285)
Well, I don't have gtk+-3.0; with gtk+2.0 it prints 'Hello world' and exits

end of strace log:
Code:

write(1, "Hello world\n", 12Hello world
)          = 12
futex(0xf6db9228, FUTEX_WAKE_PRIVATE, 2147483647) = 0
gettimeofday({1425563209, 687442}, NULL) = 0
gettimeofday({1425563209, 687520}, NULL) = 0
exit_group(0)                          = ?


Hmmm...curious.

Your test motivated me to try this same program on another Ubuntu platform. This new platform also has gtk+-3.0 on it BUT... it terminates correctly (with the exit_group).

I need to look more closely at library versions on my initial machine.

Thanks.

pan64 03-06-2015 03:09 AM

just to know: exit is the usual way in a single-threaded app and exit_group is used by multithreaded ones. The behaviour is defined by the (existence of) -pthread.

NevemTeve 03-06-2015 03:15 AM

Note: Of course it doesn't mean that user programs should use exit_group(2). It's up to exit(3) to call exit_group(2) if kernel-version if big enough.


All times are GMT -5. The time now is 08:28 AM.