Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Allegro breaks waitpid

This thread is locked; no one can reply to it. rss feed Print
Allegro breaks waitpid
Chris Katko
Member #1,881
January 2002
avatar

I've got a program (based on some Stack Overflow posts) that reads a Linux program's memory by processing /proc/%PID%/maps and then uses ptrace and waitpid to freeze a program (required), read its memory, and release it.

It works fine, until I call Allegro init and now it doesn't work. It just hangs on waitpid(). Any idea why?

Source attached. Target process PID is hardcoded at the top of the source file. To switch to "use allegro" vs "works without allegro" just scroll to bottom
in main() and set "int working" to false and it'll use Allegro.

Link simply with:

g++ reader.cpp -o reader -lallegro

[edit] OH, I just remembered. On modern kernels you have to set an environment key so you can read a program's memory.

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

And 1 to restore it. (I doubt it's permanent)

from here:

https://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process

[edit]

Also attached is my test program that simply has some simple common data, and prints its own PID. Simply run it, and then put the PID into the source code of reader.cpp. (Yeah, I could, and did, have argc/argv but I removed it for reasons.) It compiles with simple-as-possible: g++ test.cpp -o test

[edit] I just checked with getpid() and getppid() (parent PID) before and after Allegro is initialized and it doesn't appear to change it.

There ARE options with waitpid for groupip, and other criterea to wait for:

- https://linux.die.net/man/2/waitpid

But I honestly don't understand them. I tried all three/four modes of -2, -1, 0, and 1 and none of them worked. (0 being the original mode).

If I pass WNOHANG, it... won't hang. But it'll still never successfully pickup data either. Which works fine without Allegro.

[edit] I found the problem Allegro's simple test example code (and/or library calls)... are setting global errno to 11! And errno should be "reset to zero" before calls to ptrace!

The question is... why is Allegro 5 throwing errors?! The second attached reader.cpp should be the newer version with errno printf checks resulting in the following output:

[run_allegro_and_game] errno was [0]   start of function
[run_allegro_and_game] errno was [11] after al_init  <---
[run_allegro_and_game] errno was [11] al_create_timer (didn't change it?)
[run_allegro_and_game] errno was [0] al_create_display (reset it to zero?)
[run_allegro_and_game] errno was [0] al_create_event_queue
[run_allegro_and_game] errno was [0] al_register_event_source(s)
[run_allegro_and_game] errno was [11]  al_flip_display(); <----

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Elias
Member #358
May 2000

errno gets set by most libc functions - so for example if Allegro checks if configuration files exist and they don't - libc would set it to a "does not exist" error, I would assume?

--
"Either help out or stop whining" - Evert

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Excuse me please if I'm being delusional, but can't you set a hardware breakpoint on errno and watch its value change?

And also tell gdb to set it to zero and continue every time the breakpoint is hit? That would allow you to run your test normally perhaps.

EDIT
So Chris, any progress?

Should allegro be resetting errno before libc calls?

GullRaDriel
Member #3,861
September 2003
avatar

You should reset errno before any function setting it and that you want to check after.
At some point in the past it wasn't thread safe. AFAIK it's now a thread local variable so it should be more reliable than before.

That said, you only check errno in case the function returns an error, or that the function documentation specifically said otherwise. Some functions sets errno to strange values while they perfectly work.

Edit:

My common errno check is as following (from my memory):

errno=0;
if( my_func() != 0 ) /* adjust to func return code */
{
    int error = errno ; /* save errno because logging functions can change it */
    log( LOG_ERR , "func failed at line %d of %s: %s (%d)" , __LINE__ , __FILE__ , strerror( error ), error ); /* also display the value in case strerror cannot find something usefull */
}

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Chris Katko
Member #1,881
January 2002
avatar

So Chris, any progress?

Well, I know the problem. So I reset errno before I use it now.

Quote:

Should allegro be resetting errno before libc calls?

That's up to you C guys. Looks like it's standard issue for users to reset it before use, however, it should be very clear in the documentation when an Allegro function is capable of affecting a global (or TLS) variable under "side effects".

Because it's not like you're going to see "errno" directly modified by Allegro until you run into this problem. So you could easily fall into the trap of assuming you're the FIRST user of errno so it shouldn't have been touched yet.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Go to: