View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0021440FPCCompilerpublic2012-03-08 10:472012-03-14 14:00
ReporterPavel Kanzelsberger 
Assigned ToJonas Maebe 
StatusresolvedResolutionnot fixable 
PlatformDarwinOSiOSOS Version5.1
Product Version2.6.0Product Build 
Target VersionFixed in Version 
Summary0021440: FPC-compiled applications crash on iOS 5.1 when writing to stdout
DescriptioniOS application written in fps and linked in Xcode works fine when run from Xcode debugger. However when phone is restarted it is no longer working and crashing on startup.

Today I discovered what is different for app running on it's own and running from Xcode. When you connect your device to Mac and have Xcode running, it will create a temporary /Developer folder on your device and also redirect stdout/stderr:

Mar 8 10:39:46 iPhone-4[1] <Notice>: System: /Developer has appeared. launchd will redirect the stdout/stderr to the system log for all future job invocations.

However when you restart your device, this is no longer the case and fps app will crash right on startup. My wild guess right now is, something in RTL (related to stout) is trying to access non-existing location on the device and crashes...
TagsNo tags attached.
Fixed in Revision
Attached Filestxt file icon crashlog.txt [^] (20,470 bytes) 2012-03-12 21:29 [Show Content]

- Relationships

-  Notes
Pavel Kanzelsberger (reporter)
2012-03-08 11:11

I found out that basically writeln() and write() to stout will crash the program with Segmentation Fault, code 11. By avoiding writing anything to stdout will not crash the app and it works as before.
Jonas Maebe (manager)
2012-03-08 11:31

Does the rtl contain any write/writeln's to stdout? And does the same happen with a C program that contains a printf?

Even if printf doesn't crash, I'm not sure what I can do. We can't really base write/writeln on top of printf.
Jonas Maebe (manager)
2012-03-08 13:51

Also, does this C code crash?

#include <unistd.h>

int test(void)
  static const char buf[] = "test\n";

Pavel Kanzelsberger (reporter)
2012-03-08 13:54

I can do printf() from ObjC without any problems or crashes. Problem is only in fpc when linked as static library.
Jonas Maebe (manager)
2012-03-08 14:06

What about the write() from my test program?
Andru (reporter)
2012-03-12 19:07

Code above with write() function works fine.

>> Problem is only in fpc when linked as static library.
This happens not only for static library.
Jonas Maebe (manager)
2012-03-12 20:39

> This happens not only for static library.

Do you mean that something like a plain "hello world" program also crashes?

And where exactly does it crash?
Andru (reporter)
2012-03-12 21:30
edited on: 2012-03-12 21:49

>> Do you mean that something like a plain "hello world" program also crashes?
Yes, pretty simple application written fully in Pascal crashes as soon as it reaches Write/WriteLn call. And crashlog(attached) shows something strange...

Jonas Maebe (manager)
2012-03-12 22:03

Can you try compiling with -Cn, then replace crt1.o in with crt1.3.1.o, and then run to finish linking? Maybe iOS 5.1 no longer properly works with the old program startup code in crt1.o.
Andru (reporter)
2012-03-12 23:08

crt1.3.1.o didn't help.
Jonas Maebe (manager)
2012-03-13 00:35

Can you run it in gdb? Doing so without Xcode (which apparently hides the problem) may require jailbraiking though.
Andru (reporter)
2012-03-13 01:30

Sorry, jailbraiking is not an option.

>> without Xcode (which apparently hides the problem)
Seems Xcode creates some symlinks or whatever for writing to stdout/stderr, because as soon as you unplug the cable application will start to crash. And as I read here: [^] - "Apple introduced restrictions to StdOut calls". So, does FreePascal use stdout for write/writeln procedures?
Jonas Maebe (manager)
2012-03-13 11:44

> So, does FreePascal use stdout for write/writeln procedures?

Yes. But the C program I posted above also writes to stdout (file handle 1 = stdout; it's the same file handle used by FPC). So I don't understand why it would work.
Andru (reporter)
2012-03-13 13:53

I have tested that code again with Objective-C application(using Debug and Release modes) and it works... Does FreePascal use the same function? Or it calls write() via syscall/some asm code?
Jonas Maebe (manager)
2012-03-13 14:06

FPC calls plain write() from libc. However, Darwin's libc has several different versions of write(). E.g., on Mac OS X 10.5, there are:

00048d70 T _write
00048d70 T _write$NOCANCEL$UNIX2003
000137d0 T _write$UNIX2003

(as you can see, the first two are the same function, but the last one is at a different address)

You can run "nm" on the Objective-C application (or object file corresponding to the C source file in which you call write) and have a look at which "_write" symbol it lists (it will be listed as "U"). FPC currently always calls plain "_write".

Note that this does not only hold for write(), there are several other functions that also have multiple versions in libc and which are automatically aliased to one version or another.
Andru (reporter)
2012-03-13 14:30

Here is a part of nm output for release binary of Objective-C app with write() call:

00005c40 s _uniforms
         U _write
         U dyld_stub_binder
Jonas Maebe (manager)
2012-03-13 14:36

If you do that on the FPC binary, you should see exactly the same thing.

But then I don't know anymore what could cause the difference. Apparently the people from MonoTouch don't know it either, since they claim you can no longer write to stdout, while your Objective-C program proves that this is not true.
Andru (reporter)
2012-03-13 14:42
edited on: 2012-03-13 14:43

Strange, this code with direct call to write() works:

function write_C( fildes : cint; buf : PAnsiChar; nbytes : csize_t ) : csize_t; cdecl; external 'libc' name 'write';

  buf : array[ 0..1 ] of AnsiChar;
// ...
  buf[ 0 ] := 't';
  buf[ 1 ] := 0000010; // here should be a LF symbol :)
  write_C( 1, @buf[ 0 ], 2 );

Andru (reporter)
2012-03-13 14:53

Where can I find a write() call in FreeePascal sources? I tried to found it, but no luck...
Jonas Maebe (manager)
2012-03-13 15:01 [^] (it's called fpwrite in FPC).

And the function called by write(ln) to out characters is do_write() from [^]

Maybe the problem lies with errno, which is obtained via fpgeterrno declared in [^]

However, in that case almost every RTL function related to I/O would crash. Even memory allocation would then probably fail.
ddfs (reporter)
2012-03-13 15:02

I can confirm everything stated above and experienced the same issues.

write() via ObjC code works
write() via FPC code crashes
direct libc call of write() via FPC code works
Jonas Maebe (manager)
2012-03-13 15:11

As mentioned above: in FPC, you have to call fpwrite() to call the libc version of write. Plain "write" is the same as "writeln" (except that no new line is printed at the end).
ddfs (reporter)
2012-03-13 15:26
edited on: 2012-03-13 15:27

yep, I know it.
but so far I tested this call ".. cdecl; external 'libc' name 'write';" which appears to be the same as fpwrite

Andru (reporter)
2012-03-13 16:10

Almost full reconstruction of do_write() with calling FpWrite() and FpGeterrno() just works... Seems something wrong happens before do_write() call or after main part of this function.
Jonas Maebe (manager)
2012-03-13 17:01
edited on: 2012-03-13 17:02

Since fpwrite() works, I guess you can try to trace where it goes wrong. The entire chain for a "writeln('hello')" is

* fpc_Write_Text_ShortStr (in case of {$h-}) or fpc_Write_Text_AnsiStr (in case of {$h+} or {$mode delphi) in rtl/inc/
-> fpc_WriteBuffer (-> nothing, because there will be enough space in the buffer for the entire string)

* fpc_Writeln_End
-> fpc_WriteBuffer -> nothing (same as above, but for the end-of-line character)
-> TextRec(f).FlushFunc in case Do_Isdevice() returned true for the stdout handle on startup (it normally only returns that if stdout refers to a console/terminal), and in that case TextRec(f).FlushFunc contains the address of FileWriteFunc -> Do_Write

If Do_Isdevice() returned false on startup, nothing will actually be written until the program exits, or until the text buffer for stdout becomes completely full because of other write/writeln statements.

Andru (reporter)
2012-03-13 19:07
edited on: 2012-03-13 19:14

>> If Do_Isdevice() returned false on startup, nothing will actually be written until the program exits

Are sure in this? Because there is one bug on Windows. When I use -WG option application crashes on every write()/writeln() call. And I think this is because there is no available stdout too.

Jonas Maebe (manager)
2012-03-13 19:17

It's normal that Windows applications crash if you use write/writeln in a -WG compiled application. That's not a bug, that's simply how Windows works.

And do_isdevice for Windows is implemented like this:

function do_isdevice(handle:thandle):boolean;
  do_isdevice:=(handle = StdInputHandle) or (handle = StdOutputHandle) or (handle = StdErrorHandle);

So it will always return true for stdin/stdout/stderr (I know next to nothing about programming for Windows, so I don't know whether it even has any APIs that you could use to get a better result). This is however definitely not the case on Unix, where a real check takes place.
Jonas Maebe (manager)
2012-03-14 11:41

FWIW, here's yet someone else who has the problem in another environment (although he gets a hang instead of a crash): [^]
Jonas Maebe (manager)
2012-03-14 13:57

Unless someone finds other information in the near future, this seems to be an iOS restriction unrelated to FPC. I don't know why it works in plain Objective-C applications for some people, but clearly for several others even that does not work. [^] contains yet some more information.
Jonas Maebe (manager)
2012-03-14 14:00
edited on: 2012-03-14 15:45

Also, if you want to prevent stray writeln's in your program from accidentally causing crashes, adding the following at the start should help:


This will cause all output from write/writeln to the console to be redirected to /dev/null (i.e., it will be discarded).

Edit: the "input" in the code above should have read "output", of course. Fixed.

- Issue History
Date Modified Username Field Change
2012-03-08 10:47 Pavel Kanzelsberger New Issue
2012-03-08 11:11 Pavel Kanzelsberger Note Added: 0057386
2012-03-08 11:31 Jonas Maebe Note Added: 0057391
2012-03-08 13:48 Jonas Maebe FPCOldBugId => 0
2012-03-08 13:48 Jonas Maebe Summary FPC will crash on iOS 5.1 (always) => FPC-compiled applications crash on iOS 5.1 when writing to stdout
2012-03-08 13:51 Jonas Maebe Note Added: 0057400
2012-03-08 13:54 Pavel Kanzelsberger Note Added: 0057401
2012-03-08 14:06 Jonas Maebe Note Added: 0057402
2012-03-09 15:15 Jonas Maebe Status new => assigned
2012-03-09 15:15 Jonas Maebe Assigned To => Jonas Maebe
2012-03-12 19:07 Andru Note Added: 0057513
2012-03-12 20:39 Jonas Maebe Note Added: 0057525
2012-03-12 21:29 Andru File Added: crashlog.txt
2012-03-12 21:30 Andru Note Added: 0057528
2012-03-12 21:33 Andru Note Edited: 0057528
2012-03-12 21:35 Andru Note Edited: 0057528
2012-03-12 21:49 Andru Note Edited: 0057528
2012-03-12 22:03 Jonas Maebe Note Added: 0057531
2012-03-12 23:08 Andru Note Added: 0057537
2012-03-13 00:35 Jonas Maebe Note Added: 0057539
2012-03-13 01:30 Andru Note Added: 0057540
2012-03-13 11:44 Jonas Maebe Note Added: 0057569
2012-03-13 13:53 Andru Note Added: 0057575
2012-03-13 14:06 Jonas Maebe Note Added: 0057576
2012-03-13 14:30 Andru Note Added: 0057584
2012-03-13 14:36 Jonas Maebe Note Added: 0057586
2012-03-13 14:42 Andru Note Added: 0057587
2012-03-13 14:43 Andru Note Edited: 0057587
2012-03-13 14:53 Andru Note Added: 0057589
2012-03-13 15:01 Jonas Maebe Note Added: 0057590
2012-03-13 15:02 ddfs Note Added: 0057591
2012-03-13 15:11 Jonas Maebe Note Added: 0057592
2012-03-13 15:26 ddfs Note Added: 0057593
2012-03-13 15:27 ddfs Note Edited: 0057593
2012-03-13 16:10 Andru Note Added: 0057594
2012-03-13 17:01 Jonas Maebe Note Added: 0057595
2012-03-13 17:02 Jonas Maebe Note Edited: 0057595
2012-03-13 19:07 Andru Note Added: 0057602
2012-03-13 19:14 Andru Note Edited: 0057602
2012-03-13 19:17 Jonas Maebe Note Added: 0057603
2012-03-14 11:41 Jonas Maebe Note Added: 0057624
2012-03-14 13:57 Jonas Maebe Status assigned => resolved
2012-03-14 13:57 Jonas Maebe Resolution open => not fixable
2012-03-14 13:57 Jonas Maebe Note Added: 0057637
2012-03-14 14:00 Jonas Maebe Note Added: 0057639
2012-03-14 15:45 Jonas Maebe Note Edited: 0057639

MantisBT 1.2.12[^]
Copyright © 2000 - 2012 MantisBT Group
Powered by Mantis Bugtracker