Changeset 36219bc in ingen


Ignore:
Timestamp:
Nov 7, 2015, 7:19:58 PM (2 years ago)
Author:
David Robillard <d@…>
Branches:
groups, master, nodeless, parallel, parameters, sequencefix, tasks
Children:
980b93d
Parents:
9c2bb9e0
Message:

Gracefully handle UNIX socket after a crash

git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5814 a436a847-0d15-0410-975c-d299462d15a1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/server/SocketListener.cpp

    r9c2bb9e0 r36219bc  
    1717#include <errno.h>
    1818#include <poll.h>
     19#include <signal.h>
     20#include <sys/stat.h>
     21#include <unistd.h>
    1922
    2023#include <sstream>
     24#include <string>
    2125#include <thread>
    2226
     
    3539namespace Server {
    3640
     41static std::string
     42get_link_target(const char* link_path)
     43{
     44    // Stat the link to get the required size for the target path
     45    struct stat link_stat;
     46    if (lstat(link_path, &link_stat)) {
     47        return std::string();
     48    }
     49
     50    // Allocate buffer and read link target
     51    char* target = (char*)calloc(1, link_stat.st_size + 1);
     52    if (readlink(link_path, target, link_stat.st_size) != -1) {
     53        const std::string result(target);
     54        free(target);
     55        return result;
     56    }
     57
     58    return std::string();
     59}
     60
    3761void
    3862SocketListener::ingen_listen(Engine*       engine,
     
    4266    Ingen::World* world = engine->world();
    4367
    44     const std::string unix_path(world->conf().option("socket").ptr<char>());
     68    const std::string link_path(world->conf().option("socket").ptr<char>());
     69    const std::string unix_path(link_path + "." + std::to_string(getpid()));
    4570
    46     // Bind UNIX socket
     71    // Bind UNIX socket and create PID-less symbolic link
    4772    const Raul::URI unix_uri(unix_scheme + unix_path);
     73    bool            make_link = true;
    4874    if (!unix_sock->bind(unix_uri) || !unix_sock->listen()) {
    4975        world->log().error("Failed to create UNIX socket\n");
    5076        unix_sock->close();
     77        make_link = false;
    5178    } else {
    52         world->log().info(fmt("Listening on socket %1%\n") % unix_uri);
     79        const std::string old_path = get_link_target(link_path.c_str());
     80        if (!old_path.empty()) {
     81            const std::string suffix = old_path.substr(old_path.find_last_of(".") + 1);
     82            const pid_t       pid    = std::stoi(suffix);
     83            if (!kill(pid, 0)) {
     84                make_link = false;
     85                world->log().warn(fmt("Another Ingen instance is running at %1% => %2%\n")
     86                                  % link_path % old_path);
     87            } else {
     88                world->log().warn(fmt("Replacing old link %1% => %2%\n")
     89                                  % link_path % old_path);
     90                unlink(link_path.c_str());
     91            }
     92        }
     93
     94        if (make_link) {
     95            if (!symlink(unix_path.c_str(), link_path.c_str())) {
     96                world->log().info(fmt("Listening on %1%\n") %
     97                                  (unix_scheme + link_path));
     98            } else {
     99                world->log().error(fmt("Failed to link %1% => %2% (%3%)\n")
     100                                   % link_path % unix_path % strerror(errno));
     101            }
     102        } else {
     103            world->log().info(fmt("Listening on %1%\n") % unix_uri);
     104        }
    53105    }
    54106
     
    110162        }
    111163    }
     164
     165    if (make_link) {
     166        unlink(link_path.c_str());
     167    }
    112168}
    113169
Note: See TracChangeset for help on using the changeset viewer.