Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8672009
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 12, 20262026-06-12T19:05:46+00:00 2026-06-12T19:05:46+00:00

I am trying to wrangle some demo code that runs as a console application

  • 0

I am trying to wrangle some demo code that runs as a console application in Linux into a daemon.

The SDK is in c++, so I went looking for c++ code that does all the things a daemon needs to do, i.e. start, fork, detach, redirect std coms to syslog, handle signals, etc.

So I found this example:

// daemon.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <ctime>
#include <iostream>
#include <syslog.h>
#include <unistd.h>

using boost::asio::ip::udp;

class udp_daytime_server
{
public:
  udp_daytime_server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), 13))
  {
    start_receive();
  }

private:
  void start_receive()
  {
    socket_.async_receive_from(
        boost::asio::buffer(recv_buffer_), remote_endpoint_,
        boost::bind(&udp_daytime_server::handle_receive, this, _1));
  }

  void handle_receive(const boost::system::error_code& ec)
  {
    if (!ec || ec == boost::asio::error::message_size)
    {
      using namespace std; // For time_t, time and ctime;
      time_t now = time(0);
      std::string message = ctime(&now);

      boost::system::error_code ignored_ec;
      socket_.send_to(boost::asio::buffer(message),
          remote_endpoint_, 0, ignored_ec);
    }

    start_receive();
  }

  udp::socket socket_;
  udp::endpoint remote_endpoint_;
  boost::array<char, 1> recv_buffer_;
};

int main()
{
  try
  {
    boost::asio::io_service io_service;

    // Initialise the server before becoming a daemon. If the process is
    // started from a shell, this means any errors will be reported back to the
    // user.
    udp_daytime_server server(io_service);

    // Register signal handlers so that the daemon may be shut down. You may
    // also want to register for other signals, such as SIGHUP to trigger a
    // re-read of a configuration file.
    boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
    signals.async_wait(
        boost::bind(&boost::asio::io_service::stop, &io_service));

    // Inform the io_service that we are about to become a daemon. The
    // io_service cleans up any internal resources, such as threads, that may
    // interfere with forking.
    io_service.notify_fork(boost::asio::io_service::fork_prepare);

    // Fork the process and have the parent exit. If the process was started
    // from a shell, this returns control to the user. Forking a new process is
    // also a prerequisite for the subsequent call to setsid().
    if (pid_t pid = fork())
    {
      if (pid > 0)
      {
        // We're in the parent process and need to exit.
        //
        // When the exit() function is used, the program terminates without
        // invoking local variables' destructors. Only global variables are
        // destroyed. As the io_service object is a local variable, this means
        // we do not have to call:
        //
        //   io_service.notify_fork(boost::asio::io_service::fork_parent);
        //
        // However, this line should be added before each call to exit() if
        // using a global io_service object. An additional call:
        //
        //   io_service.notify_fork(boost::asio::io_service::fork_prepare);
        //
        // should also precede the second fork().
        exit(0);
      }
      else
      {
        syslog(LOG_ERR | LOG_USER, "First fork failed: %m");
        return 1;
      }
    }

    // Make the process a new session leader. This detaches it from the
    // terminal.
    setsid();

    // A process inherits its working directory from its parent. This could be
    // on a mounted filesystem, which means that the running daemon would
    // prevent this filesystem from being unmounted. Changing to the root
    // directory avoids this problem.
    chdir("/");

    // The file mode creation mask is also inherited from the parent process.
    // We don't want to restrict the permissions on files created by the
    // daemon, so the mask is cleared.
    umask(0);

    // A second fork ensures the process cannot acquire a controlling terminal.
    if (pid_t pid = fork())
    {
      if (pid > 0)
      {
        exit(0);
      }
      else
      {
        syslog(LOG_ERR | LOG_USER, "Second fork failed: %m");
        return 1;
      }
    }

    // Close the standard streams. This decouples the daemon from the terminal
    // that started it.
    close(0);
    close(1);
    close(2);

    // We don't want the daemon to have any standard input.
    if (open("/dev/null", O_RDONLY) < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Unable to open /dev/null: %m");
      return 1;
    }

    // Send standard output to a log file.
    const char* output = "/tmp/asio.daemon.out";
    const int flags = O_WRONLY | O_CREAT | O_APPEND;
    const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    if (open(output, flags, mode) < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Unable to open output file %s: %m", output);
      return 1;
    }

    // Also send standard error to the same log file.
    if (dup(1) < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Unable to dup output descriptor: %m");
      return 1;
    }

    // Inform the io_service that we have finished becoming a daemon. The
    // io_service uses this opportunity to create any internal file descriptors
    // that need to be private to the new process.
    io_service.notify_fork(boost::asio::io_service::fork_child);

    // The io_service can now be used normally.
    syslog(LOG_INFO | LOG_USER, "Daemon started");
    io_service.run();
    syslog(LOG_INFO | LOG_USER, "Daemon stopped");
  }
  catch (std::exception& e)
  {
    syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what());
    std::cerr << "Exception: " << e.what() << std::endl;
  }
}

In any case, I was wondering, is this a good choice for getting a minimal daemon up and running(replacing the udp server code and replacing with my own code), or should I look into another approach to getting daemon functionality.

I am also confused as to where I am supposed to start of my code since the final step in this example is to call io_service.run().

My code will have two threads, one to listen for a connection, and another to handle pending connections every 10 seconds->updates from the connecting clients do not have a time critical window for updates and can even occasionally be skipped.

Thank you.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-12T19:05:48+00:00Added an answer on June 12, 2026 at 7:05 pm

    If you are looking for a quick and easy implementation, then it may be a good idea. In the very least, it provides a higher-level way to handle signals, which can otherwise require a fairly detailed understanding of lower-level mechanisms to get correct. A quick implementation may look like the following:

    void connection_thread_main( bool& running )
    {
      while ( running )
        ...
    }
    
    int main()
    {
      ...
    
      syslog(LOG_INFO | LOG_USER, "Daemon started");
      // Create flag to indicate if daemon is running.  This is used as the
      // condition for which the thread's while loop continue.
      bool running = true;
    
      // Create threads.
      boost::thread_group threads;
      threads.create_thread( boost::bind( &connection_thread_main,
                                          boost::ref( running ) ) );
      threads.create_thread( boost::bind( &pending_thread_main,
                                          boost::ref( running ) ) );
    
      // This will block the main thread as long as there is work queued into the
      // service.  In this case, signals are being waited on asynchronously.
      io_service.run();
    
      // On SIGINT or SIGTERM, io_service.stop() is invoked, causing the main 
      // thread to return from io_service.run().
    
      // Set the running flag to false and wait on the other threads to finish.
      running = false;
      threads.join_all();
    
      syslog(LOG_INFO | LOG_USER, "Daemon stopped");
    }
    

    There are a few points to consider:

    • Boost.Asio provides excellent higher-level network object types. It may be worth using them instead of having to deal with lower-level types and details.
    • Although asynchronous programming has an innate complexity to it, there may be performance gains with an asynchronous implementation. As supporting thread pools is fairly easy with Boost.Asio.
    • Boost.Asio makes the signal handling easy.
    • If you decide to not use Boost.Asio, the example is a great resource on how to daemonize a process.
    • In the quick implementation, I opted to make the solution as readable as possible. As such, the main thread is basically wasted, as it is only waiting for signals. Instead of having 3 threads, it is possible to place one of the thread’s content into a loop in main, and periodically poll the io_service.

      syslog(LOG_INFO | LOG_USER, "Daemon started");
      // Create flag to indicate if daemon is running.  This is used as the
      // condition for which the thread's while loop continue.
      bool running = true;
      
      // Create threads.
      boost::thread_group threads;
      threads.create_thread( boost::bind( &connection_thread_main,
                                          boost::ref( running ) ) );
      
      for ( ;; )
      {
        // Execute ready to run handlers, but do not block waiting for
        // outstanding handlers to become ready.  When SIGINT or SIGTERM are
        // received, the handler will be ready to run, and ran from the poll
        // call, causing the io_service to stop.
        io_service.poll();
      
        if ( io_service.stopped() ) break;
      
        ... // pending_thread_main's while body content
      }    
      
      // Set the running flag to false and wait on the other threads to finish.
      running = false;
      threads.join_all();
      
      syslog(LOG_INFO | LOG_USER, "Daemon stopped");
      
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Trying to find some simple SQL Server PIVOT examples. Most of the examples that
Trying to make a MySQL-based application support MS SQL, I ran into the following
Trying to create an Oracle trigger that runs after a table is updated in
Trying to make this jQuery filter that uses .find case-insensitive. For example, when the
Trying to find some information on this but am unable to get any results
Trying to build Wireshark from source as there is no Linux installer and I
I have a prototype application (RESTful web service database front-end) that is written using
I installed the Corona SDK on MacOS. Now I'm trying to open a .lua
Trying to setup a SQL stored procedure that if the variable passed to it
Trying to use JSPX and running into a strange problem. Text inside jsp:text is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.