Skip to content

New function: pcntl_daemonize & pcntl_setaffinity. #416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ext/pcntl/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ if test "$PHP_PCNTL" != "no"; then
AC_CHECK_FUNCS(waitpid, [ AC_DEFINE(HAVE_WAITPID,1,[ ]) ], [ AC_MSG_ERROR(pcntl: waitpid() not supported by this platform) ])
AC_CHECK_FUNCS(sigaction, [ AC_DEFINE(HAVE_SIGACTION,1,[ ]) ], [ AC_MSG_ERROR(pcntl: sigaction() not supported by this platform) ])
AC_CHECK_FUNCS([getpriority setpriority wait3 sigprocmask sigwaitinfo sigtimedwait])
AC_CHECK_FUNCS(daemon, [ AC_DEFINE(HAVE_DAEMON,1,[ ]) ], [ AC_MSG_ERROR(pcntl: daemon() not supported by this platform) ])
AC_CHECK_FUNCS(sched_setaffinity, [ AC_DEFINE(HAVE_SCHED_SETAFFINITY,1,[ ]) ], [ AC_MSG_ERROR(pcntl: sched_setaffinity() not supported by this platform) ])
PHP_NEW_EXTENSION(pcntl, pcntl.c php_signal.c, $ext_shared, cli)
fi
81 changes: 81 additions & 0 deletions ext/pcntl/pcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@
#include <sys/resource.h>
#endif

#ifdef HAVE_SCHED_SETAFFINITY
#ifndef __USE_GNU
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've read __USE_GNU shouldn't be used directly: http://stackoverflow.com/questions/7296963/gnu-source-and-use-gnu
Is it right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if you want to use GNU extensions, you'd probably want to define _GNU_SOURCE before including the header (just as outlined in the man page of sched_setaffinity).

#define __USE_GNU
#endif
#include <sched.h>
#endif

#include <errno.h>

ZEND_DECLARE_MODULE_GLOBALS(pcntl)
Expand Down Expand Up @@ -137,6 +144,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setpriority, 0, 0, 1)
ZEND_END_ARG_INFO()
#endif

#ifdef HAVE_DAEMON
ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_daemonize, 0, 0, 0)
ZEND_ARG_INFO(0, nochdir)
ZEND_ARG_INFO(0, noclose)
ZEND_END_ARG_INFO()
#endif

#ifdef HAVE_SCHED_SETAFFINITY
ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_setaffinity, 0, 0, 2)
ZEND_ARG_INFO(0, pid)
ZEND_ARG_INFO(0, cpu_id)
ZEND_END_ARG_INFO()
#endif

ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_strerror, 0, 0, 1)
ZEND_ARG_INFO(0, errno)
ZEND_END_ARG_INFO()
Expand Down Expand Up @@ -171,6 +192,12 @@ const zend_function_entry pcntl_functions[] = {
#if HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT
PHP_FE(pcntl_sigwaitinfo, arginfo_pcntl_sigwaitinfo)
PHP_FE(pcntl_sigtimedwait, arginfo_pcntl_sigtimedwait)
#endif
#ifdef HAVE_DAEMON
PHP_FE(pcntl_daemonize, arginfo_pcntl_daemonize)
#endif
#ifdef HAVE_SCHED_SETAFFINITY
PHP_FE(pcntl_setaffinity, arginfo_pcntl_setaffinity)
#endif
PHP_FE_END
};
Expand Down Expand Up @@ -202,6 +229,11 @@ static void pcntl_signal_dispatch();
void php_register_signal_constants(INIT_FUNC_ARGS)
{

#ifdef HAVE_SCHED_SETAFFINITY
/* cpu affinity*/
REGISTER_LONG_CONSTANT("PCNTL_CPU_NUM", (long) sysconf(_SC_NPROCESSORS_ONLN), CONST_CS | CONST_PERSISTENT);
#endif

/* Wait Constants */
#ifdef WNOHANG
REGISTER_LONG_CONSTANT("WNOHANG", (long) WNOHANG, CONST_CS | CONST_PERSISTENT);
Expand Down Expand Up @@ -1178,6 +1210,55 @@ PHP_FUNCTION(pcntl_setpriority)
/* }}} */
#endif

#ifdef HAVE_SCHED_SETAFFINITY
/* {{{ proto bool pcntl_setaffinity(int pid, int cpu_id)
set the cpu affinity of any process */
PHP_FUNCTION(pcntl_setaffinity)
{
long pid, cpu;
cpu_set_t cpu_set;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &pid, &cpu) == FAILURE) {
return;
}
int cpu_num = sysconf(_SC_NPROCESSORS_ONLN);
if (cpu >= cpu_num) {
zend_error(E_WARNING, "cpu[%ld] not exists.", cpu);
RETURN_FALSE;
}
CPU_ZERO(&cpu_set);
CPU_SET(cpu, &cpu_set);

if (sched_setaffinity(pid, sizeof(cpu_set), &cpu_set) < 0) {
zend_error(E_WARNING, "set cpu affinity fail. errno=%d", errno);
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
#endif

#ifdef HAVE_DAEMON
/* {{{ proto bool pcntl_daemonize(int nochdir, int noclose)
run in the background */
PHP_FUNCTION(pcntl_daemonize)
{
long nochdir = 0, noclose = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &nochdir, &noclose) == FAILURE) {
return;
}

if (daemon(nochdir, noclose) < 0) {
zend_error(E_WARNING, "daemonize fail. errno=%d", errno);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather made it more readable: daemonize() falied with error %s (errno %d) and also use strerror for actual error message, since errno is rarely very informative by itself.

RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
#endif


/* {{{ proto int pcntl_get_last_error(void)
Retrieve the error number set by the last pcntl function which failed. */
PHP_FUNCTION(pcntl_get_last_error)
Expand Down
6 changes: 6 additions & 0 deletions ext/pcntl/php_pcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ PHP_FUNCTION(pcntl_getpriority);
#ifdef HAVE_SETPRIORITY
PHP_FUNCTION(pcntl_setpriority);
#endif
#ifdef HAVE_DAEMON
PHP_FUNCTION(pcntl_daemonize);
#endif
#ifdef HAVE_SCHED_SETAFFINITY
PHP_FUNCTION(pcntl_setaffinity);
#endif

struct php_pcntl_pending_signal {
struct php_pcntl_pending_signal *next;
Expand Down
15 changes: 15 additions & 0 deletions ext/pcntl/tests/pcntl_daemonize.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
pcntl_daemonize()
--SKIPIF--
<?php
if (!extension_loaded("pcntl")) print "skip";
?>
--FILE--
<?php
echo "ok. Processor will run in the background\n";
pcntl_daemonize();
sleep(10000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good idea to do this in a test.

echo "hello world\n";
?>
--EXPECT--
ok
16 changes: 16 additions & 0 deletions ext/pcntl/tests/pcntl_setaffinity.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
pcntl_setaffinity()
--SKIPIF--
<?php
if (!extension_loaded("pcntl")) print "skip";
if (!extension_loaded("posix")) print "skip";
?>
--FILE--
<?php
echo "ok. Please run 'taskset -pc ".posix_getpid()."'\n";
var_dump(pcntl_setaffinity(posix_getpid(), 0));
echo "Binding the cpu0\n";
sleep(10000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good idea for a test.

?>
--EXPECT--
ok
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it how this test works for you? Where did the rest of the echoed message go?