Objective C Command Failing When Run Through OSX Cron - objective-c

I've coded a standalone Objective C command application. If I run it through a LaunchDaemon, it runs just fine when connected by an ObjC client application over DistriutedObjects communication. If I run it at command line, it runs just fine. If I run it when called by a Bash script, it runs just fine. However, in various ways that I've attempted to run this through the root user's crontab, it does a crash report about pointer allocation:
Apr 14 05:27:00 volomike cron[72531]: cron(72531,0x7fff7d2fa000) malloc: *** error for object 0x7fb9c8400213: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Apr 14 05:27:00 volomike diagnosticd[70689]: error evaluating process info - pid: 72531, puniqueid: 72531
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.vix.cron[72531]): Service exited due to signal: Abort trap: 6
Apr 14 05:27:00 volomike com.apple.xpc.launchd[1] (com.apple.ReportCrash.Root[72550]): Endpoint has been activated through legacy launch(3) APIs. Please switch to XPC or bootstrap_check_in(): com.apple.ReportCrash.DirectoryService
Apr 14 05:27:00 volomike ReportCrash[72550]: Saved crash report for cron[72531] version 39 to /Library/Logs/DiagnosticReports/cron_2016-04-14-052700_volomike.crash
The significant part of that crash report reads:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Application Specific Information:
abort() called
*** error for object 0x7fb9c8400213: pointer being freed was not allocated
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff9490ff06 __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff9c45e4ec pthread_kill + 90
2 libsystem_c.dylib 0x00007fff9345b6e7 abort + 129
3 libsystem_malloc.dylib 0x00007fff9c02f041 free + 425
4 cron 0x000000010367aa41 0x103677000 + 14913
5 cron 0x000000010367a7e4 0x103677000 + 14308
6 cron 0x0000000103679572 0x103677000 + 9586
7 cron 0x000000010367925a 0x103677000 + 8794
8 cron 0x000000010367885e 0x103677000 + 6238
9 libdyld.dylib 0x00007fff949835ad start + 1
In the various ways, I've done it with these various cron lines, but they crash immediately when trying to call the command, and even when I have NSLog() writing stuff to /var/log/system.log all the way from the start of main to the end of the application, nothing writes -- it's like when cron tries to call my command, it dies immediately with a crash report about pointer allocation.
41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched
41 5 * * * /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched &
41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched
41 5 * * * '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched &
Note again that if I do '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched, it runs just fine, as does /bin/bash '/Applications/My App.app/Contents/Resources/mytoolcommand.sh' /q /sched, as does '/Applications/My App.app/Contents/Resources/mytoolcommand' /q /sched
I even did a variation where cron called my mytoolcommand.sh script and simply wrote Hello World to /tmp/out.txt, and it ran just fine. So, I know my crontab is working.
Can you help me figure out what I'm doing wrong? Some suspected possible issues:
Perhaps OSX El Capitan is shutting my application down for some reason, such as not being signed properly. (I'm debugging right now. I never had signature issues come up before unless it dealt with .app folders. Besides, I can run it just fine from command line without having a signature warning.)
I have debug messages loading from main() right off the bat. They should be writing to /var/log/system.log, but they're not. This tells me the application is crashing immediately when called by cron. So, is there something special I need to load into my application's libraries in order for it to run properly when called under cron?
DEVELOPMENTS
I suspected that El Capitan Gatekeeper may have been the cause. So, I created a simplistic Objective C console application like so in a main.mm file and compiled.
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *sTest = #"Hello World";
[sTest writeToFile:#"/tmp/test.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
return 0;
}
Cron seems to run this just fine, so it's not looking like a Gatekeeper problem.
I got the problem to go away, but only briefly. I recompiled the project in a brand new project, copying over source code and settings. I then ran the command through the cron about 4 times without an issue. However, when I ran it the fifth time, it failed again and continued failing.
So, I guess I'm going to have to figure out how to convert this into a LaunchAgent.

The answer is YOU DON'T. You don't use cron anymore on OSX for your applications you are coding. Instead, switch to a LaunchAgent. Sure, Apple keeps it around for POSIX support, and therefore may keep it around for a very long time, but even their website encourages people to no longer use cron for application coding.
"Note: Although it is still supported, cron is not a recommended
solution. It has been deprecated in favor of launchd."
SOURCE: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/ScheduledJobs.html
Unfortunately, though, LaunchAgents don't yet (in 10.11.4 at least) support cron-style syntax. (Yeah, I've already filed that suggestion to Apple for you.) So, there's no use of dash, comma, or backslash. Instead, it only supports an integer and multiple blocks to create each timeframe. And if that's not suitable enough, then set at least the most minimal timeframes and then do the rest of the code in whatever you are launching so that, for instance, if you want something only to run on the first Monday of the month, the LaunchDaemon launches in the first seven days but your application does a shutdown if it's not the first Monday of the month.

Related

Valgrind(memcheck) not showing all contexts

My last context/error I see in my valgrind output file is...
==3030== 1075 errors in context 61 of 540:
==3030== Syscall param ioctl(SIOCETHTOOL,ir) points to uninitialised byte(s)
==3030== at 0x7525248: ioctl (syscall-template.S:84)
==3030== by 0x686A2A7: ??? (in /lib/libpal.so)
==3030== Address 0x96cf958 is on thread 16's stack
==3030== Uninitialised value was created by a stack allocation
==3030== at 0x686A20C: ??? (in /lib/libpal.so)
...but I don't see error contexts 62 - 540. My first thought was maybe in closing the program, valgrind crashed, but after this context it printed the ERROR SUMMARY
ERROR SUMMARY: 9733 errors from 540 contexts (suppressed: 0 from 0)
I don't think it's because we came across a frame without debug info because I can see this exact same issue get hit the first time at the very beginning of my output file. Or maybe the printing of error contexts specifically, is halted when a stacktrace has missing debug info?
Any ideas? Need an additional command line argument for valgrind? I know in helgrind it'll quit after seeing 1000000 errors(something like that) but it explicitly tells you what it's doing.
So for my version of valgrind I also executed helgrind and saw all contexts(647) as expected. I think the problem above is simply a result of valgrind coming across a frame with no debug symbols and saying, "If there's no debug info, I'm moving on"
All of my logs I'm producing end with this same libpal frame at various context numbers 100-something, 200-something, etc.

open MPI - ring_c on multiple hosts fails

I have recently installed open MPI on two Ubuntu 14.04 hosts and I am now testing its functionality with the two provided test functions hello_c and ring_c. The hosts are called 'hermes' and 'zeus' and they both have the user 'mpiuser' to log in non-interactively (via ssh-agent).
The functions mpirun hello_c and mpirun --host hermes,zeus hello_c both work properly.
Calling the function mpirun --host zeus ring_c locally also works. Output for both hermes and zeus:
mpiuser#zeus:/opt/openmpi-1.6.5/examples$ mpirun --host zeus ring_c
Process 0 sending 10 to 0, tag 201 (1 processes in ring)
Process 0 sent to 0
Process 0 decremented value: 9
Process 0 decremented value: 8
Process 0 decremented value: 7
Process 0 decremented value: 6
Process 0 decremented value: 5
Process 0 decremented value: 4
Process 0 decremented value: 3
Process 0 decremented value: 2
Process 0 decremented value: 1
Process 0 decremented value: 0
Process 0 exiting
But calling the function mpirun --host zeus,hermes ring_c fails and gives following output:
mpiuser#zeus:/opt/openmpi-1.6.5/examples$ mpirun --host hermes,zeus ring_c
Process 0 sending 10 to 1, tag 201 (2 processes in ring)
[zeus:2930] *** An error occurred in MPI_Recv
[zeus:2930] *** on communicator MPI_COMM_WORLD
[zeus:2930] *** MPI_ERR_TRUNCATE: message truncated
[zeus:2930] *** MPI_ERRORS_ARE_FATAL: your MPI job will now abort
Process 0 sent to 1
--------------------------------------------------------------------------
mpirun has exited due to process rank 1 with PID 2930 on
node zeus exiting improperly. There are two reasons this could occur:
1. this process did not call "init" before exiting, but others in
the job did. This can cause a job to hang indefinitely while it waits
for all processes to call "init". By rule, if one process calls "init",
then ALL processes must call "init" prior to termination.
2. this process called "init", but exited without calling "finalize".
By rule, all processes that call "init" MUST call "finalize" prior to
exiting or it will be considered an "abnormal termination"
This may have caused other processes in the application to be
terminated by signals sent by mpirun (as reported here).
--------------------------------------------------------------------------
I haven't found any documentation on how to solve such a problem and I don't have a clue where to look for the mistake on the basis of the error output. How can I fix this?
You've changed two things between the first and second runs - you've increased the number of processes from 1 to 2, and run on multiple hosts rather than a single host.
I'd suggest you first check you can run on 2 processes on the same host:
mpirun -n 2 ring_c
and see what you get.
When debugging on a cluster it's often useful to know where each process is running. You should always print out the total number of processes as well. Try using the following code at the top of ring_c.c:
char nodename[MPI_MAX_PROCESSOR_NAME];
int namelen;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Get_processor_name(nodename, &namelen);
printf("Rank %d out of %d running on node %s\n", rank, size, nodename);
The error you're getting is saying that the incoming message is too large for the receive buffer, which is weird given that the code always sends and receives a single integer.

Image freeze when a continuation is called

I'm trying to test the continuation facility in Pharo, with this code(in the playground):
| cont f |
f:=[
|i|
i:=0.
Continuation currentDo: [ :cc | cont:=cc ].
i:=i+1.
].
f value. "1"
cont. "a Continuation"
However, as soon as I call the continuation saved in cont(replacing cont. by cont value.), the image freezes immediately, and I have to press atl+. to gain back control.
VM version: VM: NBCoInterpreter NativeBoost-CogPlugin-GuillermoPolito.19 uuid: acc98e51-2fba-4841-a965-2975997bba66 May 15 2014 NBCogit NativeBoost-CogPlugin-GuillermoPolito.19 uuid: acc98e51-2fba-4841-a965-2975997bba66 May 15 2014 https://github.com/pharo-project/pharo-vm.git Commit: ed4a4f59208968a21d82fd2406f75c2c4de558b2 Date: 2014-05-15 18:23:04 +0200 By: Esteban Lorenzano <estebanlm#gmail.com> Jenkins build #14826
Pharo version: [version] 4.0 #40614
Thanks.
Edit: I was stupid, didn't think this through...
You've effectively created an infinite loop by reevaluating the same code again and again. You can see that if you debug the code and step through it. The original context will always be restored and then evaluated starting with the first expression following the #currentDo: send. This is exactly what the continuation is supposed to do: save the current position in the execution and restart there later on.
I do not have a Fedora to test, however I tried your code in Ubuntu, using this version of Pharo:
wget -O- get.pharo.org/40+vm | bash
./pharo-ui Pharo.image
and your code seems to work properly :(
In case this error persists, could you be more specific about the version of the vm you are using?:
./pharo Pharo.image --version
And the version of Pharo you are using?:
./pharo Pharo.image printVersion
Also, send us the crash.dmp file would help a lot.

GDB script to trace Objective-C calls on iOS device - issue

I have a gdb script I am working on to trace all objective-C method calls that pass through objc_msgSend but Ive encountered a problem I cant seem to deal with. After review of the Objective-C runtime source code I have developed the following script to print [ ] at each break on objc_msgSend. The issue is that there are situations in which data_NEVER_USE is not a valid pointer but is also not null. The only indicator that I can find of whether a class is initialized is in id->data_NEVER_USE->flags & RW_REALIZED. What aspect of class initialization am I missing here that would allow me to skip this case?
b objc_msgSend
c
commands
silent
if (*$r0 == 0)
continue
end
set $id = (class_t *)$r0
set $sel = $r1
print *$id
if($id->data_NEVER_USE != 0)
set $data = (class_ro_t *) ($id->data_NEVER_USE)
if (($data->flags & 0x80000000) && ($data->name))
set $classname = $data->name
printf "[%s ", $classname
else
continue
end
end
if ($sel != 0)
printf "%s", $sel
else
printf "null"
end
printf "]\n"
continue
end
I appreciate any help on this. Thanks.
These 2 methods have worked reasonably well for me. Note that in my example I am manually starting "SomeApp" in order to monitor it as soon as it starts up.
gdb
(gdb) attach --waitfor 'SomeApp'
**this is where you manually start SomeApp on your device**
call (void)instrumentObjcMessageSends(YES)
The "instrumentObjcMessageSends" enables/disables message logging from within the runtime. Here's some more information on this method.
Another option, again still using GDB on your iDevice, is to write a small command like this:
FooPad:~ root# gdb
(gdb) attach SBSettings
Attaching to process 440.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ............................. done
0x35686004 in mach_msg_trap ()
(gdb) break objc_msgSend
Breakpoint 1 at 0x3323ef72
(gdb) commands
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>printf "-[%s %s]\n", (char *)class_getName(*(long *)$r0,$r1),$r1
>c
>end
(gdb) c
Continuing.
// a ton of information will follow
As soon as you press "c" (right above line that reads "Continuing.", your screen will fill with function names and arguments.
And finally follow these instructions to get a working GDB on your iDevice. For posterity I'll post the short instructions here:
GNU Debugger (gdb) is used to analyze the run time behavior of an iOS
application. In recent iOS versions, GNU Debugger directly downloaded
from the Cydia is broken and not functioning properly. Following the
Pod 2g blog post also did not help me.
To get rid of this problem, add http://cydia.radare.org to cydia
source and download the latest GNU Debugger (build 1708). GDB build
1708 is working for iOS 5.x.

mod_perl segmentation fault

HI,
I'm running an apache 2.2.3 on an Oracle64-bit (Red Hat clone) and I'm hitting a brick wall with an issue. I have a program which utilizes MIME::Lite to send mail through sendmail (I apologize, not sure what versions of sendmail or mod_perl I'm running, although I do believe the sendmail portion is irrelevant as you'll see in a moment)
On occasion, apache will segfault (11), and digging deep into the MIME::Lite module, I see it is on the following line:
open SENDMAIL, "|$sendmailcmd" or Carp::croak "open |$sendmailcmd: $!\n"; (this is in MIME::Lite)
Now, one would automatically suspect sendmail, but if I did the same line to use /bin/cat (as shown):
open SENDMAIL, "|/bin/cat"
apache still segfaults.
I attached an strace to the apache processes and see the following:
(when it does NOT crash)
12907 write(2, "SENDMAIL send_by_sendmail 1\n", 28) = 28
12907 write(2, "SENDMAIL /usr/lib/sendmail -t -o"..., 40) = 40
12907 pipe([24, 26]) = 0
12907 pipe([28, 29]) = 0
12907 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x2b4bcbbd75d0) = 13186
Note the "SENDMAIL sent_by_sendmail" are my comments. You can clearly see pipes opening. When it DOES crash, you'll see the following:
10805 write(2, "SENDMAIL send_by_sendmail (for y"..., 40) = 40
10805 --- SIGSEGV (Segmentation fault) # 0 (0) ---
Now notice it never pipes. I've tried GDB and it hasn't really shown me anything.
Finally, I wrote a simple program to run through mod_perl and regular cgi:
print header();
print "test";
open SENDMAIL, "|/bin/cat" or Carp::croak "open |sendmailcmd: $!\n";
print SENDMAIL "foodaddy";
close SENDMAIL;
print "test done <br/>";
Under mod_perl it has successfully crashed.
My analysis is telling me it has to do with it trying to open a file handle, the piping function returns either false or a corrupt file handle.
I also increased the file descriptor limit to 2048, no dice.
Does anyone have any thoughts as to where I should look? Any thoughts?
I appreciate the help
I just spent a long time tracking down a problem that started with identical symptoms. I eventually discovered that Test::More does not play well with mod_perl . Removing this module from my code appears to have solved the problem (so far!). I didn't follow this any deeper, but I suspect that the problem actually lies in Test::Builder.
I managed to treat perhaps only the symptoms, not the cause. I happened to have this issue when used global/package scope variables on the package level, used inside a perl object instance, as soon as I passed them as object properties instead, not as automatic default perl variables scoping, I stopped to experience perl segmentation fault suddenly.