I'm writing a simple application in C, running on a Raspberry Pi, that makes use of the D2XX drivers to communicate with a serial port device. I've followed a number of online tutorials and reference guides to get it working, and have taken steps such as setting up custom udev rules to ensure the drivers can load properly, I followed FTDI's build instructions to install the shared library, I use the -l
argument of gcc to link in the library when compiling, and I run my C program with sudo
to ensure the drivers have proper access. And that has been a success! The program works as intended.
Now I am trying to convert my simple program into a daemon process that can be controlled with an init.d script (a la service start
), and have run into trouble.
For simplicity's sake, here is a watered down version of my C program which does work:
myprog.c:
#include <stdlib.h>
#include "ftd2xx.h"
int main(int argc, char *argv[])
{
DWORD i, iNumDevs = 0;
char *serialNumber = malloc(64);
FT_STATUS ftStatus = FT_CreateDeviceInfoList(&iNumDevs);
for (i = 0; i < iNumDevs; i++) {
ftStatus = FT_ListDevices((PVOID)i, serialNumber, FT_LIST_BY_INDEX|FT_OPEN_BY_SERIAL_NUMBER);
if (FT_OK == ftStatus) {
break;
}
}
// more code here...
return EXIT_SUCCESS;
}
I compile that with gcc -lftd2xx -o myprog myprog.c
and then run it with sudo ./myprog
, and take my word for it that it does everything that it's supposed to do. But now that I am trying to re-work this same code into a daemon, I've been following some other online tutorials, and the code above has been transformed into something that looks more like this. Currently, this does not work:
mydaemon.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "ftd2xx.h"
int main(int argc, char *argv[])
{
pid_t pid, sid;
pid = fork();
if (pid < 0) {
return EXIT_FAILURE;
}
if (pid > 0) {
return EXIT_SUCCESS;
}
umask(0);
openlog("mydaemon", LOG_PID|LOG_CONS, LOG_USER);
sid = setsid();
if (sid < 0) {
syslog(LOG_ERR, "Failed to set session ID on child process");
return EXIT_FAILURE;
}
if ((chdir("/")) < 0) {
syslog(LOG_ERR, "Failed to change working directory");
return EXIT_FAILURE;
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
while (1) {
DWORD i, iNumDevs = 0;
char *serialNumber = malloc(64);
syslog(LOG_INFO, "I get to this line");
FT_STATUS ftStatus = FT_CreateDeviceInfoList(&iNumDevs);
syslog(LOG_INFO, "I do not get to this line :( ");
// more code here...
sleep(10);
}
return EXIT_SUCCESS;
}
I compile that program in the exact same way: gcc -lftd2xx -o mydaemon mydaemon.c
; I run it the same way: sudo ./mydaemon
, but unfortunately it does not work. In a separate console window I'm tailing the /var/log/messages
file, and I can clearly see it reach my first log message (i.e. "I can get to this line"), but immediately after that it is dead in the water. I never see the second log message, and indeed, at that point the program becomes totally unresponsive. I have to find its process ID and kill it.
In other words, as soon as it tries to make a call to the D2XX drivers in the forked process, it fails. What am I doing wrong? I've already demonstrated with the first example that the code does work, so what is it about running as a daemon that causes it to completely break down? As far as I can tell it doesn't even get a chance to execute the D2XX method in question; it's as if it simply can't find the method in the first place, while running in the forked process.