Changeset 36219bc in ingen


Ignore:
Timestamp:
11/07/15 19:19:58 (22 months ago)
Author:
David Robillard <d@…>
Branches:
master, groups, nodeless, parallel, parameters, sequencefix
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

    recdcc5f 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.