2015-01-14 19:11:12 +03:00
/*
2003-08-13 05:53:07 +04:00
Unix SMB / CIFS implementation .
pidfile handling
Copyright ( C ) Andrew Tridgell 1998
2017-07-31 08:11:33 +03:00
Copyright ( C ) Amitay Isaccs 2016
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( at your option ) any later version .
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2015-01-14 19:11:12 +03:00
2003-08-13 05:53:07 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
2017-07-31 07:47:01 +03:00
# include "replace.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2017-07-31 07:47:01 +03:00
# include "lib/util/blocking.h"
# include "lib/util/debug.h"
# include "lib/util/samba_util.h" /* For process_exists_by_pid() */
2012-07-20 02:41:52 +04:00
# include "lib/util/pidfile.h"
2003-08-13 05:53:07 +04:00
2021-02-15 13:38:18 +03:00
int pidfile_path_create ( const char * path , int * pfd , pid_t * existing_pid )
2017-07-31 08:11:33 +03:00
{
struct flock lck ;
char tmp [ 64 ] = { 0 } ;
int fd , ret = 0 ;
int len ;
ssize_t nwritten ;
2021-02-15 13:38:18 +03:00
bool retried = false ;
2017-07-31 08:11:33 +03:00
fd = open ( path , O_CREAT | O_WRONLY | O_NONBLOCK , 0644 ) ;
if ( fd = = - 1 ) {
return errno ;
}
if ( ! set_close_on_exec ( fd ) ) {
2021-02-15 13:38:18 +03:00
ret = errno ;
goto fail ;
2017-07-31 08:11:33 +03:00
}
2021-02-15 13:38:18 +03:00
retry :
2017-07-31 08:11:33 +03:00
lck = ( struct flock ) {
. l_type = F_WRLCK ,
. l_whence = SEEK_SET ,
} ;
do {
ret = fcntl ( fd , F_SETLK , & lck ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ret ! = 0 ) {
ret = errno ;
2021-02-15 13:38:18 +03:00
if ( ( ret = = EACCES ) | | ( ret = = EAGAIN ) ) {
do {
ret = fcntl ( fd , F_GETLK , & lck ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ret = = - 1 ) {
ret = errno ;
goto fail ;
}
if ( lck . l_type = = F_UNLCK ) {
if ( ! retried ) {
/* Lock holder died, retry once */
retried = true ;
goto retry ;
}
/* Something badly wrong */
ret = EIO ;
goto fail ;
}
if ( existing_pid ! = NULL ) {
* existing_pid = lck . l_pid ;
}
return EAGAIN ;
}
goto fail ;
2017-07-31 08:11:33 +03:00
}
/*
* PID file is locked by us so from here on we should unlink
* on failure
*/
2021-02-15 13:38:18 +03:00
len = snprintf ( tmp , sizeof ( tmp ) , " %u \n " , getpid ( ) ) ;
2017-07-31 08:11:33 +03:00
if ( len < 0 ) {
ret = errno ;
goto fail_unlink ;
}
2019-06-21 08:11:49 +03:00
if ( ( size_t ) len > = sizeof ( tmp ) ) {
2017-07-31 08:11:33 +03:00
ret = ENOSPC ;
goto fail_unlink ;
}
do {
nwritten = write ( fd , tmp , len ) ;
} while ( ( nwritten = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ( nwritten = = - 1 ) | | ( nwritten ! = len ) ) {
2021-02-15 13:38:18 +03:00
ret = errno ;
2017-07-31 08:11:33 +03:00
goto fail_unlink ;
}
2021-02-15 13:38:18 +03:00
do {
ret = ftruncate ( fd , len ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
if ( ret = = - 1 ) {
ret = errno ;
goto fail_unlink ;
2017-07-31 08:11:33 +03:00
}
2021-02-15 13:38:18 +03:00
* pfd = fd ;
2017-07-31 08:11:33 +03:00
return 0 ;
fail_unlink :
unlink ( path ) ;
2021-02-15 13:38:18 +03:00
fail :
2017-07-31 08:11:33 +03:00
close ( fd ) ;
return ret ;
}
void pidfile_fd_close ( int fd )
{
struct flock lck = {
. l_type = F_UNLCK ,
. l_whence = SEEK_SET ,
} ;
int ret ;
do {
ret = fcntl ( fd , F_SETLK , & lck ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
do {
ret = close ( fd ) ;
} while ( ( ret = = - 1 ) & & ( errno = = EINTR ) ) ;
}
2006-02-28 16:12:39 +03:00
/**
* return the pid in a pidfile . return 0 if the process ( or pidfile )
2015-01-14 19:11:12 +03:00
* does not exist
2006-02-28 16:12:39 +03:00
*/
2007-12-03 00:32:11 +03:00
pid_t pidfile_pid ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
2015-01-19 12:52:11 +03:00
size_t len = strlen ( piddir ) + strlen ( name ) + 6 ;
char pidFile [ len ] ;
2003-08-13 05:53:07 +04:00
int fd ;
2021-02-14 00:19:12 +03:00
char pidstr [ 20 ] = { 0 , } ;
2012-12-06 19:02:57 +04:00
pid_t ret = - 1 ;
2003-08-13 05:53:07 +04:00
2015-01-19 12:52:11 +03:00
snprintf ( pidFile , sizeof ( pidFile ) , " %s/%s.pid " , piddir , name ) ;
2003-08-13 05:53:07 +04:00
2004-11-01 23:21:54 +03:00
fd = open ( pidFile , O_NONBLOCK | O_RDONLY , 0644 ) ;
2005-09-26 20:57:08 +04:00
2003-08-13 05:53:07 +04:00
if ( fd = = - 1 ) {
return 0 ;
}
if ( read ( fd , pidstr , sizeof ( pidstr ) - 1 ) < = 0 ) {
goto noproc ;
}
2006-04-24 13:36:09 +04:00
ret = ( pid_t ) atoi ( pidstr ) ;
2012-06-28 05:34:25 +04:00
if ( ret < = 0 ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 1 , ( " Could not parse contents of pidfile %s \n " ,
pidFile ) ) ;
2012-06-28 05:34:25 +04:00
goto noproc ;
}
2015-01-14 19:11:12 +03:00
2008-10-17 14:48:19 +04:00
if ( ! process_exists_by_pid ( ret ) ) {
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d does not exist. \n " , ( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
2004-11-01 23:21:54 +03:00
if ( fcntl_lock ( fd , F_SETLK , 0 , 1 , F_RDLCK ) ) {
2003-08-13 05:53:07 +04:00
/* we could get the lock - it can't be a Samba process */
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is not a Samba process. \n " ,
( int ) ret ) ) ;
2003-08-13 05:53:07 +04:00
goto noproc ;
}
close ( fd ) ;
2012-07-20 03:08:16 +04:00
DEBUG ( 10 , ( " Process with PID=%d is running. \n " , ( int ) ret ) ) ;
2006-04-24 13:36:09 +04:00
return ret ;
2003-08-13 05:53:07 +04:00
noproc :
close ( fd ) ;
return 0 ;
}
2006-02-28 16:12:39 +03:00
/**
2015-01-14 19:11:12 +03:00
* create a pid file in the pid directory . open it and leave it locked
2006-02-28 16:12:39 +03:00
*/
2007-12-03 00:32:11 +03:00
void pidfile_create ( const char * piddir , const char * name )
2003-08-13 05:53:07 +04:00
{
2015-01-19 12:52:11 +03:00
size_t len = strlen ( piddir ) + strlen ( name ) + 6 ;
char pidFile [ len ] ;
2021-12-14 18:13:51 +03:00
pid_t pid = ( pid_t ) - 1 ;
2021-02-15 13:38:18 +03:00
int ret , fd ;
2003-08-13 05:53:07 +04:00
2015-01-19 12:52:11 +03:00
snprintf ( pidFile , sizeof ( pidFile ) , " %s/%s.pid " , piddir , name ) ;
2003-08-13 05:53:07 +04:00
2021-02-15 13:38:18 +03:00
ret = pidfile_path_create ( pidFile , & fd , & pid ) ;
if ( ret = = EAGAIN ) {
2015-01-14 19:11:12 +03:00
DEBUG ( 0 , ( " ERROR: %s is already running. File %s exists and process id %d is running. \n " ,
2003-08-13 05:53:07 +04:00
name , pidFile , ( int ) pid ) ) ;
exit ( 1 ) ;
}
/* Leave pid file open & locked for the duration... */
}
2012-07-20 03:08:16 +04:00
void pidfile_unlink ( const char * piddir , const char * name )
{
2021-02-14 00:19:42 +03:00
size_t len = strlen ( piddir ) + strlen ( name ) + 6 ;
char pidFile [ len ] ;
2012-07-20 03:08:16 +04:00
int ret ;
2021-02-14 00:19:42 +03:00
snprintf ( pidFile , sizeof ( pidFile ) , " %s/%s.pid " , piddir , name ) ;
2012-07-20 03:08:16 +04:00
ret = unlink ( pidFile ) ;
if ( ret = = - 1 ) {
DEBUG ( 0 , ( " Failed to delete pidfile %s. Error was %s \n " ,
pidFile , strerror ( errno ) ) ) ;
}
}