md
The cthreads Unit in Linux (Free Pascal)
March 2, 2018
<-Running a Process in a Thread (Free Pascal) --

My previous note was about running the ALSA aplay utility in a thread. I have been running into difficulty turning that approach into a general "process in a thread" module. More about that latter perhaps. In the meantime, I thought I should produce this short note to remind myself about the little twist introduced when using threads in Free Pascal for the Unix/Linux environment.

The documentation is clear,

The cthreads unit simply needs to be included in the uses clause of the program, preferably the very first unit, and the initialization section of the unit will do all the work.

Note that including this unit links your program to the C library of the system.

It makes no sense to use this unit on a non-posix system: Windows, OS/2 or DOS, therefor it should always between an ifdef statement:

program myprogram;
uses
   {$ifdef unix}cthreads{$endif},
   classes, sysutils;

The Lazarus IDE inserts this conditional automatically for each new started program.

Actually, this is not quite how it works at least on my version of the Lazarus IDE. If I depend on this supposed automatic mechanism, here is the error message I get.

When the Break button is clicked then the listing in the Assembler window makes it clear that there is a thread error of some type.

Starting the program in a terminal will be even more informative.

michel@hp:~/Development/fpl-projects$
./myprogram
This binary has no thread support compiled in. Recompile the application with a thread-driver in the program uses clause before other units using thread.

The same output can be seen when running the program from the IDE. To see its output, open Console window by pressing the key combination AltCtrlO or selecting it from the menu: View/Debug Windows/Terminal Output.

The problem is that cthread is not loaded by default and the reason becomes the clear when looking at the program source (IDE menu: Project/View Project Source).

program myprogram; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Interfaces, // this includes the LCL widgetset

Note how cthread is wrapped in two conditional directives. While UNIX is defined, UseCThreads is not which explains the missing unit.

The solution is simply to remove the {$IFDEF UseCThreads} and matching {£ENDIF}.

Another solution is to define the directive. Do this in the Project Options window. This window is displayed by choosing Project/Project Options in the menu, and Custom Options in the Compiler Options in the list of options on the left. For each defined Build modes, click on the Defines... button on the right hand and start typing the name of the define UseCThreads in the edit window. The Add button will be enabled, click on it when UseCThreads is fully entered.

The define will then be listed below along with a checkbox to the left. Check this box and click on the OK button.

I go through the above steps three times, once for each build mode. Is there an easier way of adding this define? Perhaps just editing the project source code is more efficient.

<-Running a Process in a Thread (Free Pascal) --