LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 04-04-2019, 06:57 PM   #1
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Rep: Reputation: 13
pthread_create, immediate seg fault


Centos, g++, linux novice, first attempt at threads.

Edit: See post 13 for the solution

I am trying to create my first thread. I start the app and it gets to the part to start the thread and cores out. Here is the code but please be tolerant of typos as I cannot copy paste from my work computer to here.
this is running inside a Qt widget, and within that an OpenGL widget. All of that was working before trying to add the thread and the symptoms indicate, to me, the problem is at the thread creation.

EDIT: I have change the descriptions of the files since the OP


File get_one_parameter.h declares

Code:
st_parameter_and_time  m_p_and_t;     // a structure with some strings, ints, etc
pthread_t              m_thread_info;

The code of the tread to start is in get_one_parameter.cpp and the code to run begins with

Code:
void * Get_One_Parameter( void * arg )
{    // this is line 21
   st_parameter_and_time *p_and_t
   p_and_t = ( st_parameter_and_time  * )  arg;
.... } // it does not do much yet.
File gl_strip_chart.h declares the class that the thread is started from. It contains:

Code:
...
class C_GL_Strip_Chart : public QGLWidget
{...
   st_parameter_and_time   m_p_and_t;
   pthread_t               m_thread_indo;
... }

The code to start the thread is in the constructor of class c_gl_strip_chart
and the file name is gl_strip_chart.cpp

The code to start the thread is:
Code:
...
std::cout <<  "\nthread start now" << std::endl;
int thread_status = pthread_create( &( m_thread_into ),
                                       0,
                                       Get_One_Parameter,
                                       &m_p_and_t );
std::cout << "\nstart status = " << thread_status << std::endl;
...
Since it cored out right away it was started within gdb and the terminal window contains:

Quote:
Starting program .....
[New Thread 0x7fffe387f700 (LWP 38233)
<blank line>
thread start now
[NewThread 0x7fffdddfb700 (LWP 38239)]
<blank line>
Program received signal SIGSEGV, Segmentation fault.
[Switching to thread 0x7fffdddfb700 (LWP 38239) ]
0x00000000004326e6a in Get_One_Parameter( arg = <error reading variable: Cannot access memory at 0x7fffd9dfad28 at get_one_parameter.cpp:21
21 {
Missing separate debuginfos, // and continues on for multiple lines.
I am hoping my error is obvious to the more experienced developer.
I looked diligently for typos and hope any remaining are obvious.

Last edited by bkelly; 04-16-2019 at 01:16 PM. Reason: additional information
 
Old 04-04-2019, 08:23 PM   #2
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
m_p_and_t occupies no actual memory.

You can reference it in an include file but you have to declare it in a C file.
 
Old 04-05-2019, 10:18 AM   #3
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by rtmistler View Post
m_p_and_t occupies no actual memory.

You can reference it in an include file but you have to declare it in a C file.
I don't understand how that can be. So I put some print statements in the code to show addresses as follows:

Code:
std::cout << "\n address of m_p_and_t = "        << (uint64_t ) &m_p_and_t        << std::flush;
std::cout << "\n address of m_p_and_t.stream = " << (uint64_t ) &m_p_and_t.stream << std::flush;
std::cout << "\n address of m_p_and_t.parm = "   << (uint64_t ) &m_p_and_t.parm   << std::flush;
etc
The values looked reasonable and as I worked through the structure incremented by 8 or 4 depending on the type of item.

Maybe I need to elaborate on the file names.

The first mentioned h file is: gl_strip_chart.h
Those are member variables within the class c_gl_strip_chart

The structure is declared in show_one_parameter.h
The thread code is in show_one_parameter.cpp

The code to start the thread is in: gl_strip_chart.cpp
And that code is in the constructor of class c_gl_strip_chart


In file gl_strip_chart.h the member name of the structure was changed to mpt;
Then in the constructure, just above the std::cout lines was added:

st_parameter_and_time m_p_and_t;

The goal was to create/instantiate it just before the code that starts the thread, recognizing that it is local to the constructor, but this is a test.
The results were exactly the same.

Meanwhile, I will edit the clarifications into the OP.

Last edited by bkelly; 04-05-2019 at 10:29 AM. Reason: formatting
 
Old 04-05-2019, 11:46 AM   #4
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
A coworker that was unable to make this work holds the position that the structure passed into the pthread_create() must be either static or global. My searches about pthread_create() did not reveal that requirement. Any thoughts on that aspect?
 
Old 04-05-2019, 12:13 PM   #5
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
I agree that it could be global. Sorry hadn't noticed that it was a member of a class. You need that object to exist somewhere, prior to sending it as an argument to a new thread.
 
Old 04-05-2019, 01:00 PM   #6
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
I burned through all my co-workers without a solution. The system architect with more experience that all the rest of us put together came by, looked at the memory maps and said that the argument going into the thread was not right. Could not say why, just flat out wrong. He could see that the memory addresses are not right, meaning the proximate cause for the coring, but not the root cause.

Then he said that since this is within Qt and Open GL, that some things are known to be weird and do not work right. His suggestion is to use the threads functions within Qt rather than the normal pthread_create(). I am taking that path now. That will take a bit of time.

After a few more searches for tutorials and I have not recognized anything that says pthreads must be static or global.

Last edited by bkelly; 04-05-2019 at 01:01 PM.
 
Old 04-05-2019, 01:47 PM   #7
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
The language of Qt is C++.

Meanwhile Qt does have its own thread classes.

I suggest searching for pthread examples on the web, there are plenty.
 
Old 04-08-2019, 10:17 AM   #8
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
The thought occurred that moving the code to be created as a thread into the class might make the difference. I have not been able to derive a syntax that is acceptable to the compiler. Here is one attempt along with the error message.

Code:
void * ptr_test;
ptr_test = (void * ) 0;
void * get_one_void;
get_one_void = (void * ) * C_GL_Strip_Chart::Get_One_Parameter;

int thread status = pthread_create( & ( m_thread_info ),
                                    0,
                                    get_one_void,
                                    ptr_test );
The error is:

Quote:
Cannot convert ‘C_GL_Strip_Chart::Get_One_Parameter’ from type ‘void* (C_GL_Strip_Chart:: )(void*)’ to type ‘void* (*)(void*)’
After some additional lines about include file paths this is displayed:

Quote:
… initializing argument 3 of ‘int pthread_create( pthread_t*, const pthread_artt_t*, void*, void* (*)(void*), void*)’ [-fpermissive]
That tells me the argument for the thread to run is incorrect. I am pretty sure there are a few typos in there as I find this difficult to transcribe. I hope they are sufficiently few in number to allow the concept to be conveyed.
 
Old 04-08-2019, 12:41 PM   #9
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,882
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
To be honest, I never have had excellent luck when there's code which doesn't work, or compile, or execute correctly. I have tried things like that and sometimes they get worse. Meanwhile, I go (what I call) "back to basics" and I grab a known good example of pthread'ing or whichever code example I'm looking for, in the language I'm looking for it in. I'm not sure if there are Qt specific ones, I do know as I said before that Qt has a QThread class of it's own and that there are examples of that. Once I get that first working example, I go from there and see if I can get it to attain what I want. The other primary thing to do is to use the debugger to resolve things like if memory is not allocated for the process, etc. Sorry, but that's about the best I have here. I don't personally have an exact example that would suit what you're looking for.

What that error is telling you is that pthread_create() is expecting a certain prototype for one of the arguments. Besides example, the manual page of pthread_create() can also help there. But it says it wants a void* (*)(void*).
 
Old 04-08-2019, 01:24 PM   #10
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,838

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
pthread_create accept general pointers, because it is a general function. You need to cast this function pointer, otherwise you will get that cannot convert error.
From the other hand you need to pass the pointer to the function and you need the "address-of" operator here (&).
https://stackoverflow.com/questions/...ember-function
 
Old 04-11-2019, 04:57 PM   #11
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
I am flip/flopping between the Qt threads and the Linux thread. On the Linux thread side I modified the code that starts the thread to look like this:

Code:
std::cout << "\n"m_pt address = " << std::hex << (uint64_t) &m_pt << std::endl;

status = pthread(create( & m_thread_info,
                           0,
                           Get_One_Param,
                           & m_pt )
Where m_pt is a member variable that is a structure to pass to the thread.
In GDB before the core details is the text:

Quote:
m_pt address = 73ed70
Further down it states:

Quote:
... error reading variable: Cannot access memory at address 0x7fffd95afd18>) ad get_one_parameter.cpp:21
line 21 remains the open brace of the function started as the thread.

Within gdb enter the command: print arg
the response is:

Quote:
Cannot access memory at address 0x7fffd95afd18
Just in case I typed wrong, that's the same address first mentioned.

So just for fun tried this:

Code:
uint64_t force address = (uint64_t) & m_pt;
status = pthread_create( & m_thread_info,
                           0,
                           Get_One_Param,
                           (void * ) force_address );
The end result is the same. The address for "arg" within GDB and within the started thread is not the same as that in the pthread_create call.

And just in case, the code to be started as the thread starts off like this:

Code:
void * Get_One_Param( void * arg )
{   // this is line 21,  nothing here but the open brace.
...
}
And just in case, there is a GDB command: show args so I changed the opening line to:

Code:
void * Get_One_Param( void * input_address )
{
...
}
And everything is the same.
Summary
When Get_One_Parm is started the argument list, which I understand is to be the address of something that can be referenced by the thread, is an invalid address. I don't know what I might do to fix that.

Edit: forgot one more permutation:

Code:
status = pthread_create( & m_thread_info,
                           0,
                           Get_One_Param,
                           (void * ) 0 );  // Note the zero here
And the result was exactly the same addresses as before. The address in argument 4 is not getting through to the code that is started. Argument 4 appears to be totally ignored. I don't have a clue as to where it ( with it meaning the compiler, the Centos O.S., or I don't know) might be getting the address handed to the thread. Co-workers are using pthread_create without a problem.

Edit again:
So the debugger is showing that the address does not match that provided by the call to pthread_create(...)
However, since I do have what I appears to be the correct address, what might happen if, within that function Get_One_Parm, I were to use GDB and change the incoming argument to be the value shown before the call, and then attempt to continue running.
I am looking at my cheat sheet and do not recognize any command that might do this. Can it be done?
Edit last time:
I tried the command:
Code:
set var input_address = 73ed70  //the address from the std::cout statement.
The response is:
Quote:
Cannot access memory at 0x7fffd95afd18
GDB appears to have ignored the set variable command.

Last edited by bkelly; 04-11-2019 at 05:38 PM.
 
Old 04-12-2019, 01:51 AM   #12
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,838

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
what you posted is more or less meaningless without the real code you tried.
 
Old 04-16-2019, 01:15 PM   #13
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
I have resolved the problem but do not know if this is the solution or a work-around.
The thread uses a class to read data from something called the ION buss, a commercial product.
I was creating the class in the H file for the thread as in

Code:
C_Read_Class m_read_class
After a while I moved the class to be completely within the thread code, within the .cpp file, as in:

Code:
void * Get_One_Param( void * input_address )
{ ...
   C_Read_Class * m_read_class;

   m_read_class = new C_Read_Class;
}
This change resolved the problem.
Is this the way a class must be used with pthread_create()?

Last edited by bkelly; 04-17-2019 at 10:19 AM.
 
Old 04-16-2019, 01:19 PM   #14
bkelly
Member
 
Registered: Jan 2008
Distribution: Centos 7-4
Posts: 205

Original Poster
Rep: Reputation: 13
Quote:
Originally Posted by pan64 View Post
what you posted is more or less meaningless without the real code you tried.
I think what was posted is far from meaningless. However, your concept is exactly right. In my attempts at being brief I omitted what turned out to be the problem.
 
  


Reply

Tags
pthread_create, segfault



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
seg fault / mem fault - in cron, but works in shell? kauaikat Red Hat 1 04-29-2008 04:24 PM
seg fault / mem fault - in cron, but works in shell? kauaikat Linux - Software 1 04-29-2008 08:21 AM
Immediate Segmentation Fault PatrickNew Programming 10 12-31-2006 03:45 PM
kudzu failed seg fault itschaotic Linux - Newbie 2 01-27-2002 12:17 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 12:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration