Skip to content
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

add thread:setname and thread:getname #208

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
28 changes: 28 additions & 0 deletions config.h.guess
Original file line number Diff line number Diff line change
Expand Up @@ -853,5 +853,33 @@
#define STRERROR_R_CHAR_P ((AG_GLIBC_PREREQ(0,0) || AG_UCLIBC_PREREQ(0,0,0)) && (HAVE__GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)))
#endif

#ifndef HAVE_GLIBC_PTHREAD
Copy link
Collaborator

Choose a reason for hiding this comment

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

The define is only really about pthread_setname, please rename them all accordingly

Copy link
Author

Choose a reason for hiding this comment

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

Different pthread implementations have different function signatures, and some only have setname and no getname. That's why I've introduced the HAVE_<PLATFORM>_PTHREAD macro as welll as HAVE_PTHREAD_SETNAME and HAVE_PTHREAD_GETNAME.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think that really makes sense though: the values you've chosen here are very geared to the setname call.
e.g. glibc had pthreads long before 2.12.

Copy link
Author

Choose a reason for hiding this comment

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

true -- i'll use some other name then

#define HAVE_GLIBC_PTHREAD (AG_GLIBC_PREREQ(2,12) && __linux__)
#endif

#ifndef HAVE_NETBSD_PTHREAD
/*5.0.0 has setname() but no getname(). let's not support it for now.*/
#define HAVE_NETBSD_PTHREAD (AG_NETBSD_PREREQ(6,0,0))
#endif

#ifndef HAVE_FREEBSD_PTHREAD
#define HAVE_FREEBSD_PTHREAD (AG_FREEBSD_PREREQ(5,2,1))
#endif

#ifndef HAVE_OPENBSD_PTHREAD
#define HAVE_OPENBSD_PTHREAD (AG_OPENBSD_PREREQ(3,6))
#endif

#ifndef HAVE_MACOSX_PTHREAD
#define HAVE_MACOSX_PTHREAD (AG_MACOS_PREREQ(10,7,0))
#endif

#ifndef HAVE_PTHREAD_SETNAME
#define HAVE_PTHREAD_SETNAME (HAVE_GLIBC_PTHREAD || HAVE_NETBSD_PTHREAD || HAVE_FREEBSD_PTHREAD || HAVE_OPENBSD_PTHREAD || HAVE_MACOSX_PTHREAD)
#endif

#ifndef HAVE_PTHREAD_GETNAME
#define HAVE_PTHREAD_GETNAME (HAVE_GLIBC_PTHREAD || HAVE_NETBSD_PTHREAD || HAVE_MACOSX_PTHREAD)
#endif

#endif /* CONFIG_H_GUESS */
10 changes: 10 additions & 0 deletions doc/cqueues.tex
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,16 @@ \subsubsection{\fn{signal[]}}

Returns a boolean and error value. If false, error value is an error code describing a local error, usually \errno{EAGAIN} or \errno{ETIMEDOUT}. If true, error value is 1) an error code describing a system error which the thread encountered, 2) an error message string returned by the new Lua instance, or 3) nil if completed successfully.

\subsubsection[\fn{thread:setname}]{\fn{thread:setname(name)}}
Set a name for the thread. The name must be a string not exceeding 15 characters in length. Supported on Linux, FreeBSD, NetBSD, OpenBSD. \& Mac OS X. On OS X this function only works from inside the thread.

Returns true on success, false, an error string, an error string and the errno if the name is too long or if the platform does not support this function.

\subsubsection[\fn{thread:getname}]{\fn{thread:getname(name)}}
Get the name of the thread. Supported on Linux, NetBSD \& Mac OS X.

Returns the name string, or nil, an error string and the errno if the platform does not support this function.

\end{Module}

\begin{Module}{cqueues.notify}
Expand Down
96 changes: 96 additions & 0 deletions src/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include <sys/socket.h>

#include <pthread.h>
#if (HAVE_OPENBSD_PTHREAD || HAVE_FREEBSD_PTHREAD)
#include <pthread_np.h>
#endif

#include <dlfcn.h>

Expand Down Expand Up @@ -755,6 +758,97 @@ static int ct_timeout(lua_State *L) {
return 0;
} /* ct_timeout() */

#if HAVE_PTHREAD_SETNAME
static int ct_setname(lua_State *L) {
struct cthread *ct = ct_checkthread(L, 1);
char *name = luaL_checkstring(L, 2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

there is too much whitespace here.

int rc;
#if HAVE_GLIBC_PTHREAD
rc = pthread_setname_np(ct->id, name);
#elif HAVE_NETBSD_PTHREAD
rc = pthread_setname_np(ct->id, "%s", name);
#elif (HAVE_FREEBSD_PTHREAD || HAVE_OPENBSD_PTHREAD)
rc = 0;
/* from FreeBSD & OpenBSD man page:
Because of the debugging nature of this function, all errors that may
appear inside are silently ignored.
*/
pthread_set_name_np(ct->id, name);
#elif HAVE_MACOSX_PTHREAD
if (pthread_equal(ct->id, pthread_self())) {
lua_pushboolean(L, 0);
lua_pushliteral(L, "thread name cannot be set from outside the thread on this platform");

This comment was marked as resolved.

lua_pushinteger(L, EPERM);
return 3;
}
rc = pthread_setname_np(name);
#endif
switch(rc) {
case 0:
lua_pushboolean(L, 1);
return 1;
case ERANGE:
lua_pushboolean(L, 0);
lua_pushliteral(L, "thread name too long");
lua_pushinteger(L, rc);
return 3;
case EINVAL:
lua_pushboolean(L, 0);
lua_pushliteral(L, "invalid parameter when setting thread name");
lua_pushinteger(L, rc);
return 3;
case ENOMEM:
lua_pushboolean(L, 0);
lua_pushliteral(L, "out of memory when setting thread name");
lua_pushinteger(L, rc);
return 3;
}
} /* ct_setname() */
#else
static int ct_setname(lua_State *L) {
lua_pushnil(L);
lua_pushliteral(L, "setname() not supported on this platform");
lua_pushinteger(L, EPERM);
return 3;
} /* ct_setname() */
#endif


#if HAVE_PTHREAD_GETNAME
static int ct_getname(lua_State *L) {
struct cthread *ct = ct_checkthread(L, 1);
char buf[128];
int rc = EINVAL;
/*all the pthread_getname_np interfaces are the same where supported*/
rc = pthread_getname_np(ct->id, buf, 128);
switch(rc) {
case ERANGE:
lua_pushnil(L);
lua_pushliteral(L, "thread name too long");
lua_pushinteger(L, rc);
return 3;
case EINVAL:
lua_pushnil(L);
lua_pushliteral(L, "invalid parameter when getting thread name");
lua_pushinteger(L, rc);
return 3;
case ENOMEM:
lua_pushnil(L);
lua_pushliteral(L, "out of memory when getting thread name");
lua_pushinteger(L, rc);
return 3;
}
lua_pushstring(L, buf);
return 1;
} /* ct_getname() */
#else
static int ct_getname(lua_State *L) {
lua_pushnil(L);
lua_pushliteral(L, "getname() not supported on this platform");
lua_pushinteger(L, EPERM);
return 3;
} /* ct_getname() */
#endif

static int ct__eq(lua_State *L) {
struct cthread **a = luaL_testudata(L, 1, CQS_THREAD);
Expand Down Expand Up @@ -804,6 +898,8 @@ static const luaL_Reg ct_methods[] = {
{ "pollfd", &ct_pollfd },
{ "events", &ct_events },
{ "timeout", &ct_timeout },
{ "setname", &ct_setname },
{ "getname", &ct_getname },
{ NULL, NULL }
};

Expand Down