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+ #define pid_t int ;
39+ #else
40+ #include < unistd.h>
41+ #endif
42+
3443using json = nlohmann::ordered_json;
3544
3645constexpr int HTTP_POLLING_SECONDS = 1 ;
@@ -3691,6 +3700,77 @@ inline void signal_handler(int signal) {
36913700 shutdown_handler (signal);
36923701}
36933702
3703+ static bool check_pid_alive (const pid_t pid) {
3704+ if (pid <= 0 ) {
3705+ return false ;
3706+ }
3707+
3708+ // Process is alive or exists but is inaccessible
3709+ if (kill (pid, 0 ) == 0 || errno == EPERM) {
3710+ return true ; // Process is alive
3711+ }
3712+
3713+ return false ; // Process does not exist or other error
3714+ }
3715+
3716+ class PidFile {
3717+ public:
3718+ FILE * file = nullptr ;
3719+ std::string fname;
3720+ bool rm = false ;
3721+
3722+ FILE * open (const std::string & filename, const char * mode, const bool r = false ) {
3723+ file = ggml_fopen (filename.c_str (), mode);
3724+ fname = filename;
3725+ rm = r;
3726+
3727+ return file;
3728+ }
3729+
3730+ void close () {
3731+ fclose (file);
3732+ file = nullptr ;
3733+
3734+ if (rm) {
3735+ // Remove stale pidfile
3736+ unlink (fname.c_str ());
3737+ }
3738+ }
3739+
3740+ ~PidFile () {
3741+ if (file) {
3742+ close ();
3743+ }
3744+ }
3745+ };
3746+
3747+ static bool is_old_pid_alive (const std::string & filename) {
3748+ pid_t oldpid = 0 ;
3749+ PidFile f;
3750+ if (f.open (filename, " r" )) {
3751+ if (fscanf (f.file , " %d" , &oldpid) == 1 ) {
3752+ if (check_pid_alive (oldpid)) {
3753+ LOG_ERR (" Process already running with PID %d\n " , oldpid);
3754+ return true ;
3755+ }
3756+ }
3757+ }
3758+
3759+ return false ;
3760+ }
3761+
3762+ static int create_pidfile (const std::string & pidfile, PidFile & f) {
3763+ if (!f.open (pidfile.c_str (), " w" , true )) {
3764+ LOG_ERR (" Unable to open pidfile %s: %s\n " , pidfile.c_str (), strerror (errno));
3765+ return -1 ;
3766+ }
3767+
3768+ fprintf (f.file , " %d\n " , getpid ());
3769+ fflush (f.file );
3770+
3771+ return 0 ;
3772+ }
3773+
36943774int main (int argc, char ** argv) {
36953775 // own arguments required by this example
36963776 common_params params;
@@ -3699,6 +3779,13 @@ int main(int argc, char ** argv) {
36993779 return 1 ;
37003780 }
37013781
3782+ PidFile f;
3783+ if (!params.pidfile .empty ()) {
3784+ if (is_old_pid_alive (params.pidfile ) || create_pidfile (params.pidfile , f)) {
3785+ return 1 ;
3786+ }
3787+ }
3788+
37023789 common_init ();
37033790
37043791 // struct that contains llama context and inference
0 commit comments