1414// mime type for sending response
1515#define MIMETYPE_JSON " application/json; charset=utf-8"
1616
17- // auto generated files (see README.md for details)
18- #include " index.html.gz.hpp"
19- #include " loading.html.hpp"
17+ #include < signal.h>
2018
2119#include < atomic>
2220#include < chrono>
21+ #include < cinttypes>
2322#include < condition_variable>
2423#include < cstddef>
25- #include < cinttypes>
2624#include < deque>
2725#include < memory>
2826#include < mutex>
29- #include < signal.h>
3027#include < thread>
3128#include < unordered_map>
3229#include < unordered_set>
3330
31+ // auto generated files (see README.md for details)
32+ #include " index.html.gz.hpp"
33+ #include " loading.html.hpp"
34+
35+ #ifdef _WIN32
36+ #include < process.h>
37+ #define getpid _getpid
38+ #else
39+ #include < unistd.h>
40+ #endif
41+
3442using json = nlohmann::ordered_json;
3543
3644constexpr int HTTP_POLLING_SECONDS = 1 ;
@@ -3691,6 +3699,77 @@ inline void signal_handler(int signal) {
36913699 shutdown_handler (signal);
36923700}
36933701
3702+ static bool check_pid_alive (const pid_t pid) {
3703+ if (pid <= 0 ) {
3704+ return false ;
3705+ }
3706+
3707+ // Process is alive or exists but is inaccessible
3708+ if (kill (pid, 0 ) == 0 || errno == EPERM) {
3709+ return true ; // Process is alive
3710+ }
3711+
3712+ return false ; // Process does not exist or other error
3713+ }
3714+
3715+ class PidFile {
3716+ public:
3717+ FILE * file = nullptr ;
3718+ std::string fname;
3719+ bool rm = false ;
3720+
3721+ FILE * open (const std::string & filename, const char * mode, const bool r = false ) {
3722+ file = ggml_fopen (filename.c_str (), mode);
3723+ fname = filename;
3724+ rm = r;
3725+
3726+ return file;
3727+ }
3728+
3729+ void close () {
3730+ fclose (file);
3731+ file = nullptr ;
3732+
3733+ if (rm) {
3734+ // Remove stale pidfile
3735+ unlink (fname.c_str ());
3736+ }
3737+ }
3738+
3739+ ~PidFile () {
3740+ if (file) {
3741+ close ();
3742+ }
3743+ }
3744+ };
3745+
3746+ static bool is_old_pid_alive (const std::string & filename) {
3747+ pid_t oldpid = 0 ;
3748+ PidFile f;
3749+ if (f.open (filename, " r" )) {
3750+ if (fscanf (f.file , " %d" , &oldpid) == 1 ) {
3751+ if (check_pid_alive (oldpid)) {
3752+ LOG_ERR (" Process already running with PID %d\n " , oldpid);
3753+ return true ;
3754+ }
3755+ }
3756+ }
3757+
3758+ return false ;
3759+ }
3760+
3761+ static int create_pidfile (const std::string & pidfile, PidFile & f) {
3762+ if (!f.open (pidfile.c_str (), " w" , true )) {
3763+ LOG_ERR (" Unable to open pidfile %s: %s\n " , pidfile.c_str (), strerror (errno));
3764+ return -1 ;
3765+ }
3766+
3767+ fprintf (f.file , " %d\n " , getpid ());
3768+ fflush (f.file );
3769+
3770+ return 0 ;
3771+ }
3772+
36943773int main (int argc, char ** argv) {
36953774 // own arguments required by this example
36963775 common_params params;
@@ -3699,6 +3778,13 @@ int main(int argc, char ** argv) {
36993778 return 1 ;
37003779 }
37013780
3781+ PidFile f;
3782+ if (!params.pidfile .empty ()) {
3783+ if (is_old_pid_alive (params.pidfile ) || create_pidfile (params.pidfile , f)) {
3784+ return 1 ;
3785+ }
3786+ }
3787+
37023788 common_init ();
37033789
37043790 // struct that contains llama context and inference
0 commit comments