Merge branch 'master' of github.com:urbit/urbit

This commit is contained in:
C. Guy Yarvin 2014-04-02 18:07:29 -07:00
commit ed075b8029
56 changed files with 1403 additions and 288 deletions

View File

@ -83,7 +83,7 @@ u2_cf_path(c3_c* top_c,
c3_w top_w = strlen(top_c);
c3_w len_w = _cf_path_1(0, (top_w + 1), tah);
c3_w buf_w = len_w + (ext_c ? (1 + strlen(ext_c)) : 0);
c3_c* buf_c = malloc(buf_w + 1);
c3_c* buf_c = c3_malloc(buf_w + 1);
c3_w pos_w;
u2_noun pas;
@ -162,7 +162,7 @@ u2_cf_flat_load(u2_noun mod,
}
fln_w = sat_s.st_size;
fil_c = malloc(sat_s.st_size);
fil_c = c3_malloc(sat_s.st_size);
if ( fln_w != read(fid_i, fil_c, fln_w) ) {
return u2_none;
@ -238,7 +238,7 @@ u2_cf_flat_save(u2_noun mod,
}
fln_w = u2_met(3, som);
fil_y = malloc(fln_w);
fil_y = c3_malloc(fln_w);
u2_cr_bytes(0, fln_w, fil_y, som);
u2_cz(som);
@ -301,7 +301,7 @@ c3_c*
u2_cr_string(u2_atom a)
{
c3_w met_w = u2_cr_met(3, a);
c3_c* str_c = malloc(met_w + 1);
c3_c* str_c = c3_malloc(met_w + 1);
u2_cr_bytes(0, met_w, (c3_y*)str_c, a);
str_c[met_w] = 0;
@ -319,7 +319,7 @@ u2_cr_tape(u2_noun a)
for ( i_w = 0, b=a; u2_yes == u2du(b); i_w++, b=u2t(b) )
;
a_y = malloc(i_w + 1);
a_y = c3_malloc(i_w + 1);
for ( i_w = 0, b=a; u2_yes == u2du(b); i_w++, b=u2t(b) ) {
a_y[i_w] = u2h(b);
@ -361,7 +361,7 @@ u2_ci_chubs(c3_w a_w,
{
// XX considerably suboptimal
{
c3_w *b_w = malloc(a_w * 8);
c3_w *b_w = c3_malloc(a_w * 8);
c3_w i_w;
u2_atom p;

View File

@ -153,7 +153,7 @@ _cs_save(u2_ho_cash* cas_s,
void* qtr_v = per_p->ptr_v;
u2_ho_cash* cax_s;
if ( 0 == (cax_s = malloc(sizeof(*cax_s))) ) {
if ( 0 == (cax_s = c3_malloc(sizeof(*cax_s))) ) {
return;
}
_cs_init(cax_s);
@ -349,7 +349,7 @@ u2_ho_cstring(u2_noun xip) // retain
c3_w len_w = _ho_mop_chip(0, xip);
c3_c *cos_c;
if ( !(cos_c = malloc(len_w + 1)) ) abort();
if ( !(cos_c = c3_malloc(len_w + 1)) ) abort();
_ho_mop_chip(cos_c, xip);
cos_c[len_w] = 0;
@ -385,7 +385,7 @@ _ho_down(u2_ho_hangar *hag)
void
u2_ho_push(void)
{
u2_ho_hangar *hag = malloc(sizeof(u2_ho_hangar));
u2_ho_hangar *hag = c3_malloc(sizeof(u2_ho_hangar));
_ho_boot(hag);
hag->nex_h = u2_HostHangar;
@ -531,13 +531,13 @@ _ho_explore_dummy(u2_rail ral_r,
{
u2_ho_driver *dry_d;
if ( !(dry_d = malloc(sizeof(u2_ho_driver))) ) {
if ( !(dry_d = c3_malloc(sizeof(u2_ho_driver))) ) {
abort();
}
dry_d->cos_c = cos_c;
dry_d->sub_d = 0;
dry_d->xip = xip;
if ( !(dry_d->fan_j = malloc(sizeof(u2_ho_jet))) ) {
if ( !(dry_d->fan_j = c3_malloc(sizeof(u2_ho_jet))) ) {
abort();
}
dry_d->fan_j->fcs_c = 0;

View File

@ -325,14 +325,28 @@ _loom_start(void)
{
struct rlimit rlm;
#define LOOM_STACK (65536 << 10)
getrlimit(RLIMIT_STACK, &rlm);
rlm.rlim_cur = 65536 << 10;
setrlimit(RLIMIT_STACK, &rlm);
rlm.rlim_cur = rlm.rlim_max > LOOM_STACK ? LOOM_STACK : rlm.rlim_max;
if ( 0 != setrlimit(RLIMIT_STACK, &rlm) ) {
perror("stack");
exit(1);
}
#undef LOOM_STACK
getrlimit(RLIMIT_NOFILE, &rlm);
rlm.rlim_cur = 4096;
setrlimit(RLIMIT_NOFILE, &rlm);
if ( 0 != setrlimit(RLIMIT_NOFILE, &rlm) ) {
perror("file limit");
// no exit, not a critical limit
}
getrlimit(RLIMIT_CORE, &rlm);
rlm.rlim_cur = RLIM_INFINITY;
if ( 0 != setrlimit(RLIMIT_CORE, &rlm) ) {
perror("core limit");
// no exit, not a critical limit
}
}
signal(SIGINT, _loom_stop);
}

View File

@ -164,7 +164,7 @@ u2_ux_read(u2_ray wir_r,
}
fln_w = sat_s.st_size;
fil_c = malloc(sat_s.st_size);
fil_c = c3_malloc(sat_s.st_size);
if ( fln_w != read(fid_i, fil_c, fln_w) ) {
return u2_none;
@ -240,7 +240,7 @@ u2_ux_write(u2_wire wir_r,
return u2_no;
}
fln_w = u2_met(3, som);
fil_y = malloc(fln_w);
fil_y = c3_malloc(fln_w);
u2_bytes(0, fln_w, fil_y, som);
if ( fln_w != write(fid_i, fil_y, fln_w) ) {

View File

@ -71,7 +71,7 @@
{
c3_w i_w;
loc_u->hev = malloc(u2_ckb_lent(u2k(hev)) * sizeof(u2_noun));
loc_u->hev = c3_malloc(u2_ckb_lent(u2k(hev)) * sizeof(u2_noun));
for ( i_w = 0; u2_nul != hev; i_w++ ) {
loc_u->hev[i_w] = u2h(hev);
@ -80,7 +80,7 @@
loc_u->lev_w = i_w;
}
loc_u->kct_w = 0;
loc_u->kad = malloc(
loc_u->kad = c3_malloc(
(1 + c3_min(loc_u->lev_w, loc_u->lel_w)) *
sizeof(u2_noun));

View File

@ -20,7 +20,7 @@
u2_atom a) // retain
{
c3_w met_w = u2_met(3, a);
c3_y* fat_y = malloc(met_w + 1);
c3_y* fat_y = c3_malloc(met_w + 1);
u2_bytes(0, met_w, fat_y, a);
{
@ -51,7 +51,7 @@
u2_atom b) // retain
{
c3_assert(u2_fly_is_cat(a));
c3_y* fat_y = malloc(a + 1);
c3_y* fat_y = c3_malloc(a + 1);
u2_bytes(0, a, fat_y, b);
{

View File

@ -88,3 +88,7 @@
} \
cnt_w = (cnt_w + 1) % (n); \
} while (0)
/* c3_malloc(): asserting malloc
*/
void*
c3_malloc(size_t s);

View File

@ -503,30 +503,28 @@
u2_bean vog; // did they vote for us?
} u2_rnam;
/* u2_opts:
/* u2_opts: command line configuration.
*/
typedef struct _u2_opts {
c3_c* cpu_c;
c3_c* imp_c;
c3_c* hom_c;
c3_c* nam_c;
c3_c* raf_c;
c3_w kno_w;
c3_w fuz_w;
c3_s por_s;
c3_s rop_s;
u2_bean abo;
u2_bean bat;
u2_bean gab;
u2_bean dem;
u2_bean loh;
u2_bean pro;
u2_bean veb;
u2_bean pas;
u2_bean rez;
u2_bean sow;
u2_bean nuu;
u2_bean vno;
c3_c* cpu_c; // pier name
c3_c* imp_c; // -I, czar name
c3_c* hom_c; // -h, urbit home
c3_c* nam_c; // -n, unix hostname
c3_c* raf_c; // -r, raft flotilla
c3_w kno_w; // -k, kernel version
c3_w fuz_w; // -f, fuzz testing
c3_s por_s; // -p, ames port
c3_s rop_s; // -l, raft port
u2_bean abo; // -a
u2_bean bat; // -b, batch create
u2_bean gab; // -g
u2_bean dem; // -d, dem
u2_bean fog; // -Xwtf, skip last event
u2_bean loh; // -L, local-only networking
u2_bean pro; // , profile
u2_bean veb; // -v, verbose (inverse of -q)
u2_bean nuu; // -c, new pier
u2_bean vno; // -V
} u2_opts;
/* u2_host: entire host.

View File

@ -3,6 +3,7 @@
*.l[oa]
*.opensdf
*.orig
*.pyc
*.sdf
*.suo
core

View File

@ -6,6 +6,7 @@ Brian White <mscdex@mscdex.net>
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
Frank Denis <github@pureftpd.org>
Isaac Z. Schlueter <i@izs.me>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>

View File

@ -85,3 +85,12 @@ Miroslav Bajtoš <miro.bajtos@gmail.com>
Elliot Saba <staticfloat@gmail.com>
Wynn Wilkes <wynnw@movenetworks.com>
Andrei Sedoi <bsnote@gmail.com>
Chris Bank <cbank@adobe.com>
Geert Jansen <geertj@gmail.com>
Alex Gaynor <alex.gaynor@gmail.com>
huxingyi <huxingyi@msn.com>
Alex Crichton <alex@alexcrichton.com>
Luca Bruno <lucab@debian.org>
Trevor Norris <trev.norris@gmail.com>
Oguz Bastemur <obastemur@gmail.com>
Alexis Campailla <alexis@janeasystems.com>

View File

@ -1,4 +1,141 @@
2013.07.26, Version 0.10.13 (Stable)
2014.02.19, Version 0.10.25 (Stable)
Changes since version 0.10.24:
* stream: start thread after assignments (Oguz Bastemur)
* unix: correct error when calling uv_shutdown twice (Saúl Ibarra Corretgé)
* windows: freeze in uv_tcp_endgame (Alexis Campailla)
* sunos: handle rearm errors (Fedor Indutny)
2014.01.30, Version 0.10.24 (Stable), aecd296b6bce9b40f06a61c5c94e43d45ac7308a
Changes since version 0.10.23:
* linux: move sscanf() out of the assert() (Trevor Norris)
* linux: fix C99/C++ comment (Fedor Indutny)
2014.01.23, Version 0.10.23 (Stable), dbd218e699fec8be311d85e4788be9e28ae884f8
Changes since version 0.10.22:
* linux: relax assumption on /proc/stat parsing (Luca Bruno)
* openbsd: fix obvious bug in uv_cpu_info (Fedor Indutny)
* process: close stdio after dup2'ing it (Fedor Indutny)
2014.01.08, Version 0.10.22 (Stable), f526c90eeff271d9323a9107b9a64a4671fd3103
Changes since version 0.10.21:
* windows: avoid assertion failure when pipe server is closed (Bert Belder)
2013.12.19, Version 0.10.21 (Stable), 375ebce068555f0ca8151b562edb5f1b263022db
Changes since version 0.10.20:
* unix: fix a possible memory leak in uv_fs_readdir (Alex Crichton)
2013.12.13, Version 0.10.20 (Stable), 04141464dd0fba90ace9aa6f7003ce139b888a40
Changes since version 0.10.19:
* linux: fix up SO_REUSEPORT back-port (Ben Noordhuis)
* fs-event: fix invalid memory access (huxingyi)
2013.11.13, Version 0.10.19 (Stable), 33959f7524090b8d2c6c41e2400ca77e31755059
Changes since version 0.10.18:
* darwin: avoid calling GetCurrentProcess (Fedor Indutny)
* unix: update events from pevents between polls (Fedor Indutny)
* fsevents: support japaneese characters in path (Chris Bank)
* linux: don't turn on SO_REUSEPORT socket option (Ben Noordhuis)
* build: fix windows smp build with gyp (Geert Jansen)
* linux: handle EPOLLHUP without EPOLLIN/EPOLLOUT (Ben Noordhuis)
* unix: fix reopened fd bug (Fedor Indutny)
* core: fix fake watcher list and count preservation (Fedor Indutny)
2013.10.19, Version 0.10.18 (Stable), 9ec52963b585e822e87bdc5de28d6143aff0d2e5
Changes since version 0.10.17:
* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis)
* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis)
* unix: revert recent FSEvent changes (Ben Noordhuis)
* unix: fix non-synchronized access in signal.c (Ben Noordhuis)
2013.09.25, Version 0.10.17 (Stable), 9670e0a93540c2f0d86c84a375f2303383c11e7e
Changes since version 0.10.16:
* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis)
* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis)
2013.09.06, Version 0.10.16 (Stable), 2bce230d81f4853a23662cbeb26fe98010b1084b
Changes since version 0.10.15:
* windows: make uv_shutdown() for write-only pipes work (Bert Belder)
* windows: make uv_fs_open() report EINVAL when invalid arguments are passed
(Bert Belder)
* windows: make uv_fs_open() report _open_osfhandle() failure correctly (Bert
Belder)
* windows: make uv_fs_chmod() report errors correctly (Bert Belder)
* windows: wrap multi-statement macros in do..while block (Bert Belder)
2013.08.24, Version 0.10.15 (Stable), 221078a8fdd9b853c6b557b3d9a5dd744b4fdd6b
Changes since version 0.10.14:
* fsevents: create FSEvents thread on demand (Ben Noordhuis)
* fsevents: use a single thread for interacting with FSEvents, because it's not
thread-safe. (Fedor Indutny)
* fsevents: share FSEventStream between multiple FS watchers, which removes a
limit on the maximum number of file watchers that can be created on OS X.
(Fedor Indutny)
2013.08.22, Version 0.10.14 (Stable), 15d64132151c18b26346afa892444b95e2addad0
Changes since version 0.10.13:
* unix: retry waitpid() on EINTR (Ben Noordhuis)
2013.07.26, Version 0.10.13 (Stable), 381312e1fe6fecbabc943ccd56f0e7d114b3d064
Changes since version 0.10.12:

View File

@ -91,12 +91,12 @@ Or:
Unix users run
./gyp_uv -f make
./gyp_uv.py -f make
make -C out
Macintosh users run
./gyp_uv -f xcode
./gyp_uv.py -f xcode
xcodebuild -project uv.xcodeproj -configuration Release -target All
Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and

View File

@ -74,6 +74,7 @@ TESTS= \
test/test-delayed-accept.o \
test/test-dlerror.o \
test/test-embed.o \
test/test-emfile.o \
test/test-error.o \
test/test-fail-always.o \
test/test-fs.o \
@ -97,6 +98,7 @@ TESTS= \
test/test-ping-pong.o \
test/test-pipe-bind-error.o \
test/test-pipe-connect-error.o \
test/test-pipe-server-close.o \
test/test-platform-output.o \
test/test-poll.o \
test/test-poll-close.o \
@ -107,6 +109,7 @@ TESTS= \
test/test-semaphore.o \
test/test-shutdown-close.o \
test/test-shutdown-eof.o \
test/test-shutdown-twice.o \
test/test-signal.o \
test/test-signal-multiple-loops.o \
test/test-spawn.o \
@ -114,6 +117,7 @@ TESTS= \
test/test-tcp-bind6-error.o \
test/test-tcp-bind-error.o \
test/test-tcp-close.o \
test/test-tcp-close-accept.o \
test/test-tcp-close-while-connecting.o \
test/test-tcp-connect6-error.o \
test/test-tcp-connect-error-after-write.o \
@ -142,6 +146,7 @@ TESTS= \
test/test-udp-send-and-recv.o \
test/test-util.o \
test/test-walk-handles.o \
test/test-watcher-cross-stop.o \
.PHONY: all bench clean clean-platform distclean test

View File

@ -116,6 +116,7 @@ test/test-pass-always.c
test/test-ping-pong.c
test/test-pipe-bind-error.c
test/test-pipe-connect-error.c
test/test-pipe-server-close.c
test/test-platform-output.c
test/test-poll-close.c
test/test-poll.c
@ -133,6 +134,7 @@ test/test-stdio-over-pipes.c
test/test-tcp-bind-error.c
test/test-tcp-bind6-error.c
test/test-tcp-close-while-connecting.c
test/test-tcp-close-accept.c
test/test-tcp-close.c
test/test-tcp-connect-error-after-write.c
test/test-tcp-connect-error.c
@ -161,6 +163,7 @@ test/test-udp-options.c
test/test-udp-send-and-recv.c
test/test-util.c
test/test-walk-handles.c
test/test-watcher-cross-stop.c
"
case `uname -s` in

View File

@ -171,7 +171,6 @@
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
'PREBINDING': 'NO', # No -Wl,-prebind
'USE_HEADERMAP': 'NO',
'OTHER_CFLAGS': [

View File

@ -75,7 +75,7 @@ if __name__ == '__main__':
if sys.platform != 'win32':
if '-f' not in args:
args.extend('-f make'.split())
if 'ninja' not in args:
if 'eclipse' not in args and 'ninja' not in args:
args.extend(['-Goutput_dir=' + output_dir])
args.extend(['--generator-output', output_dir])
(major, minor), is_clang = compiler_version()

View File

@ -595,20 +595,33 @@ static unsigned int next_power_of_two(unsigned int val) {
static void maybe_resize(uv_loop_t* loop, unsigned int len) {
uv__io_t** watchers;
void* fake_watcher_list;
void* fake_watcher_count;
unsigned int nwatchers;
unsigned int i;
if (len <= loop->nwatchers)
return;
nwatchers = next_power_of_two(len);
watchers = realloc(loop->watchers, nwatchers * sizeof(loop->watchers[0]));
/* Preserve fake watcher list and count at the end of the watchers */
if (loop->watchers != NULL) {
fake_watcher_list = loop->watchers[loop->nwatchers];
fake_watcher_count = loop->watchers[loop->nwatchers + 1];
} else {
fake_watcher_list = NULL;
fake_watcher_count = NULL;
}
nwatchers = next_power_of_two(len + 2) - 2;
watchers = realloc(loop->watchers,
(nwatchers + 2) * sizeof(loop->watchers[0]));
if (watchers == NULL)
abort();
for (i = loop->nwatchers; i < nwatchers; i++)
watchers[i] = NULL;
watchers[nwatchers] = fake_watcher_list;
watchers[nwatchers + 1] = fake_watcher_count;
loop->watchers = watchers;
loop->nwatchers = nwatchers;
@ -700,6 +713,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
uv__io_stop(loop, w, UV__POLLIN | UV__POLLOUT);
ngx_queue_remove(&w->pending_queue);
/* Remove stale events for this file descriptor */
uv__platform_invalidate_fd(loop, w->fd);
}

View File

@ -36,14 +36,22 @@ int uv__set_process_title(const char* title) {
CFStringRef,
CFStringRef,
CFDictionaryRef*);
typedef CFDictionaryRef (*LSApplicationCheckInType)(int, CFDictionaryRef);
typedef OSStatus (*SetApplicationIsDaemonType)(int);
typedef void (*LSSetApplicationLaunchServicesServerConnectionStatusType)(
uint64_t, void*);
CFBundleRef launch_services_bundle;
LSGetCurrentApplicationASNType ls_get_current_application_asn;
LSSetApplicationInformationItemType ls_set_application_information_item;
CFStringRef* display_name_key;
ProcessSerialNumber psn;
CFTypeRef asn;
CFStringRef display_name;
OSStatus err;
CFBundleRef hi_services_bundle;
LSApplicationCheckInType ls_application_check_in;
SetApplicationIsDaemonType set_application_is_daemon;
LSSetApplicationLaunchServicesServerConnectionStatusType
ls_set_application_launch_services_server_connection_status;
launch_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
@ -71,8 +79,36 @@ int uv__set_process_title(const char* title) {
if (display_name_key == NULL || *display_name_key == NULL)
return -1;
/* Force the process manager to initialize. */
GetCurrentProcess(&psn);
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIServices"));
if (hi_services_bundle == NULL)
return -1;
set_application_is_daemon = CFBundleGetFunctionPointerForName(
hi_services_bundle,
CFSTR("SetApplicationIsDaemon"));
ls_application_check_in = CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSApplicationCheckIn"));
ls_set_application_launch_services_server_connection_status =
CFBundleGetFunctionPointerForName(
launch_services_bundle,
CFSTR("_LSSetApplicationLaunchServicesServerConnectionStatus"));
if (set_application_is_daemon == NULL ||
ls_application_check_in == NULL ||
ls_set_application_launch_services_server_connection_status == NULL) {
return -1;
}
if (set_application_is_daemon(1) != noErr)
return -1;
ls_set_application_launch_services_server_connection_status(0, NULL);
/* Check into process manager?! */
ls_application_check_in(-2,
CFBundleGetInfoDictionary(CFBundleGetMainBundle()));
display_name = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
asn = ls_get_current_application_asn();

View File

@ -202,9 +202,12 @@ static ssize_t uv__fs_readdir(uv_fs_t* req) {
int i;
int n;
dents = NULL;
n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort);
if (n == -1 || n == 0)
if (n == 0)
goto out; /* osx still needs to deallocate some memory */
else if (n == -1)
return n;
len = 0;
@ -232,7 +235,7 @@ static ssize_t uv__fs_readdir(uv_fs_t* req) {
out:
saved_errno = errno;
{
if (dents != NULL) {
for (i = 0; i < n; i++)
free(dents[i]);
free(dents);
@ -302,7 +305,7 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
*
* 1. Read errors are reported only if nsent==0, otherwise we return nsent.
* The user needs to know that some data has already been sent, to stop
* him from sending it twice.
* them from sending it twice.
*
* 2. Write errors are always reported. Write errors are bad because they
* mean data loss: we've read data but now we can't write it out.

View File

@ -223,9 +223,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
handle->realpath_len = strlen(handle->realpath);
/* Initialize paths array */
path = CFStringCreateWithCString(NULL,
handle->filename,
CFStringGetSystemEncoding());
path = CFStringCreateWithFileSystemRepresentation(NULL, handle->filename);
paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
latency = 0.15;

View File

@ -183,6 +183,7 @@ uint64_t uv__hrtime(void);
int uv__kqueue_init(uv_loop_t* loop);
int uv__platform_loop_init(uv_loop_t* loop, int default_loop);
void uv__platform_loop_delete(uv_loop_t* loop);
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);
/* various */
void uv__async_close(uv_async_t* handle);

View File

@ -162,9 +162,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
nevents = 0;
assert(loop->watchers != NULL);
loop->watchers[loop->nwatchers] = (void*) events;
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
for (i = 0; i < nfds; i++) {
ev = events + i;
fd = ev->ident;
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;
w = loop->watchers[fd];
if (w == NULL) {
@ -191,7 +197,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
revents = 0;
if (ev->filter == EVFILT_READ) {
if (w->events & UV__POLLIN) {
if (w->pevents & UV__POLLIN) {
revents |= UV__POLLIN;
w->rcount = ev->data;
} else {
@ -205,7 +211,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (ev->filter == EVFILT_WRITE) {
if (w->events & UV__POLLOUT) {
if (w->pevents & UV__POLLOUT) {
revents |= UV__POLLOUT;
w->wcount = ev->data;
} else {
@ -227,6 +233,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->cb(loop, w, revents);
nevents++;
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
@ -255,6 +263,25 @@ update_timeout:
}
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct kevent* events;
uintptr_t i;
uintptr_t nfds;
assert(loop->watchers != NULL);
events = (struct kevent*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
if (events == NULL)
return;
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
if ((int) events[i].ident == fd)
events[i].ident = -1;
}
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
uv_fs_event_t* handle;
struct kevent ev;

View File

@ -97,6 +97,25 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event* events;
uintptr_t i;
uintptr_t nfds;
assert(loop->watchers != NULL);
events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
if (events == NULL)
return;
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
if ((int) events[i].data == fd)
events[i].data = -1;
}
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct uv__epoll_event events[1024];
struct uv__epoll_event* pe;
@ -189,10 +208,17 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
nevents = 0;
assert(loop->watchers != NULL);
loop->watchers[loop->nwatchers] = (void*) events;
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->data;
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;
assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);
@ -208,9 +234,38 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
continue;
}
w->cb(loop, w, pe->events);
nevents++;
/* Give users only events they're interested in. Prevents spurious
* callbacks when previous callback invocation in this loop has stopped
* the current watcher. Also, filters out events that users has not
* requested us to watch.
*/
pe->events &= w->pevents | UV__POLLERR | UV__POLLHUP;
/* Work around an epoll quirk where it sometimes reports just the
* EPOLLERR or EPOLLHUP event. In order to force the event loop to
* move forward, we merge in the read/write events that the watcher
* is interested in; uv__read() and uv__write() will then deal with
* the error or hangup in the usual fashion.
*
* Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
* reads the available data, calls uv_read_stop(), then sometime later
* calls uv_read_start() again. By then, libuv has forgotten about the
* hangup and the kernel won't report EPOLLIN again because there's
* nothing left to read. If anything, libuv is to blame here. The
* current hack is just a quick bandaid; to properly fix it, libuv
* needs to remember the error/hangup event. We should get that for
* free when we switch over to edge-triggered I/O.
*/
if (pe->events == UV__EPOLLERR || pe->events == UV__EPOLLHUP)
pe->events |= w->pevents & (UV__EPOLLIN | UV__EPOLLOUT);
if (pe->events != 0) {
w->cb(loop, w, pe->events);
nevents++;
}
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
@ -546,9 +601,11 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
/* skip "cpu<num> " marker */
{
unsigned int n = num;
unsigned int n;
int r = sscanf(buf, "cpu%u ", &n);
assert(r == 1);
(void) r; /* silence build warning */
for (len = sizeof("cpu0"); n /= 10; len++);
assert(sscanf(buf, "cpu%u ", &n) == 1 && n == num);
}
/* Line contains user, nice, system, idle, iowait, irq, softirq, steal,
@ -575,6 +632,7 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
ci[num++].cpu_times = ts;
}
fclose(fp);
assert(num == numcpus);
return 0;
}

View File

@ -223,7 +223,7 @@ uv_err_t uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uint64_t info[CPUSTATES];
char model[512];
int numcpus = 1;
static int which[] = {CTL_HW,HW_MODEL,0};
int which[] = {CTL_HW,HW_MODEL,0};
size_t size;
int i;
uv_cpu_info_t* cpu_info;

View File

@ -73,7 +73,9 @@ static void uv__chld(uv_signal_t* handle, int signum) {
assert(signum == SIGCHLD);
for (;;) {
pid = waitpid(-1, &status, WNOHANG);
do
pid = waitpid(-1, &status, WNOHANG);
while (pid == -1 && errno == EINTR);
if (pid == 0)
return;
@ -184,7 +186,7 @@ skip:
/*
* Used for initializing stdio streams like options.stdin_stream. Returns
* zero on success.
* zero on success. See also the cleanup section in uv_spawn().
*/
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
int mask;
@ -288,32 +290,41 @@ static void uv__process_child_init(uv_process_options_t options,
close_fd = pipes[fd][0];
use_fd = pipes[fd][1];
if (use_fd >= 0)
close(close_fd);
else if (fd >= 3)
continue;
else {
/* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
* set
*/
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
if (use_fd < 0) {
if (fd >= 3)
continue;
else {
/* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
* set
*/
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
close_fd = use_fd;
if (use_fd == -1) {
uv__write_int(error_fd, errno);
perror("failed to open stdio");
_exit(127);
if (use_fd == -1) {
uv__write_int(error_fd, errno);
perror("failed to open stdio");
_exit(127);
}
}
}
if (fd == use_fd)
uv__cloexec(use_fd, 0);
else {
else
dup2(use_fd, fd);
close(use_fd);
}
if (fd <= 2)
uv__nonblock(fd, 0);
if (close_fd != -1)
close(close_fd);
}
for (fd = 0; fd < stdio_count; fd++) {
use_fd = pipes[fd][1];
if (use_fd >= 0 && fd != use_fd)
close(use_fd);
}
if (options.cwd && chdir(options.cwd)) {
@ -461,11 +472,18 @@ int uv_spawn(uv_loop_t* loop,
error:
uv__set_sys_error(process->loop, errno);
for (i = 0; i < stdio_count; i++) {
close(pipes[i][0]);
close(pipes[i][1]);
if (pipes != NULL) {
for (i = 0; i < stdio_count; i++) {
if (i < options.stdio_count)
if (options.stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
continue;
if (pipes[i][0] != -1)
close(pipes[i][0]);
if (pipes[i][1] != -1)
close(pipes[i][1]);
}
free(pipes);
}
free(pipes);
return -1;
}

View File

@ -141,7 +141,10 @@ static void uv__signal_handler(int signum) {
saved_errno = errno;
memset(&msg, 0, sizeof msg);
uv__signal_lock();
if (uv__signal_lock()) {
errno = saved_errno;
return;
}
for (handle = uv__signal_first_handle(signum);
handle != NULL && handle->signum == signum;

View File

@ -282,6 +282,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
int fds[2];
int ret;
int kq;
int old_fd;
kq = kqueue();
if (kq == -1) {
@ -333,16 +334,20 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s->fake_fd = fds[0];
s->int_fd = fds[1];
if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
goto fatal4;
old_fd = *fd;
s->stream = stream;
stream->select = s;
*fd = s->fake_fd;
if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
goto fatal4;
return 0;
fatal4:
s->stream = NULL;
stream->select = NULL;
*fd = old_fd;
close(s->fake_fd);
close(s->int_fd);
s->fake_fd = -1;
@ -679,8 +684,8 @@ static void uv__write_req_finish(uv_write_t* req) {
/* Only free when there was no error. On error, we touch up write_queue_size
* right before making the callback. The reason we don't do that right away
* is that a write_queue_size > 0 is our only way to signal to the user that
* he should stop writing - which he should if we got an error. Something to
* revisit in future revisions of the libuv API.
* they should stop writing - which they should if we got an error. Something
* to revisit in future revisions of the libuv API.
*/
if (req->error == 0) {
if (req->bufs != req->bufsml)
@ -1075,6 +1080,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
if (!(stream->flags & UV_STREAM_WRITABLE) ||
stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_STREAM_SHUTTING ||
stream->flags & UV_CLOSED ||
stream->flags & UV_CLOSING) {
uv__set_artificial_error(stream->loop, UV_ENOTCONN);

View File

@ -87,6 +87,25 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
}
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct port_event* events;
uintptr_t i;
uintptr_t nfds;
assert(loop->watchers != NULL);
events = (struct port_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
if (events == NULL)
return;
/* Invalidate events with same file descriptor */
for (i = 0; i < nfds; i++)
if ((int) events[i].portev_object == fd)
events[i].portev_object = -1;
}
void uv__io_poll(uv_loop_t* loop, int timeout) {
struct port_event events[1024];
struct port_event* pe;
@ -173,10 +192,17 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
nevents = 0;
assert(loop->watchers != NULL);
loop->watchers[loop->nwatchers] = (void*) events;
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->portev_object;
/* Skip invalidated events, see uv__platform_invalidate_fd */
if (fd == -1)
continue;
assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);
@ -193,6 +219,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (w->pevents != 0 && ngx_queue_empty(&w->watcher_queue))
ngx_queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
}
loop->watchers[loop->nwatchers] = NULL;
loop->watchers[loop->nwatchers + 1] = NULL;
if (nevents != 0) {
if (nfds == ARRAY_SIZE(events) && --count != 0) {
@ -275,9 +303,9 @@ void uv_loadavg(double avg[3]) {
#if defined(PORT_SOURCE_FILE)
static void uv__fs_event_rearm(uv_fs_event_t *handle) {
static int uv__fs_event_rearm(uv_fs_event_t* handle) {
if (handle->fd == -1)
return;
return 0;
if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
@ -285,8 +313,10 @@ static void uv__fs_event_rearm(uv_fs_event_t *handle) {
FILE_ATTRIB | FILE_MODIFIED,
handle) == -1) {
uv__set_sys_error(handle->loop, errno);
return -1;
}
handle->fd = PORT_LOADED;
return 0;
}
@ -333,11 +363,12 @@ static void uv__fs_event_read(uv_loop_t* loop,
assert(events != 0);
handle->fd = PORT_FIRED;
handle->cb(handle, NULL, events, 0);
if (handle->fd != PORT_DELETED)
if (uv__fs_event_rearm(handle) != 0)
handle->cb(handle, NULL, 0, -1);
}
while (handle->fd != PORT_DELETED);
if (handle != NULL && handle->fd != PORT_DELETED)
uv__fs_event_rearm(handle);
}
@ -359,14 +390,16 @@ int uv_fs_event_init(uv_loop_t* loop,
}
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
uv__handle_start(handle); /* FIXME shouldn't start automatically */
handle->filename = strdup(filename);
handle->fd = PORT_UNUSED;
handle->cb = cb;
memset(&handle->fo, 0, sizeof handle->fo);
handle->fo.fo_name = handle->filename;
uv__fs_event_rearm(handle);
if (uv__fs_event_rearm(handle) != 0)
return -1;
uv__handle_start(handle); /* FIXME shouldn't start automatically */
if (first_run) {
uv__io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd);

View File

@ -286,6 +286,31 @@ static void uv__udp_sendmsg(uv_loop_t* loop,
}
/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional
* refinements for programs that use multicast.
*
* Linux as of 3.9 has a SO_REUSEPORT socket option but with semantics that
* are different from the BSDs: it _shares_ the port rather than steal it
* from the current listener. While useful, it's not something we can emulate
* on other platforms so we don't enable it.
*/
static int uv__set_reuse(int fd) {
int yes;
#if defined(SO_REUSEPORT) && !defined(__linux__)
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
return -errno;
#else
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
return -errno;
#endif
return 0;
}
static int uv__bind(uv_udp_t* handle,
int domain,
struct sockaddr* addr,
@ -293,6 +318,7 @@ static int uv__bind(uv_udp_t* handle,
unsigned flags) {
int saved_errno;
int status;
int err;
int yes;
int fd;
@ -321,30 +347,12 @@ static int uv__bind(uv_udp_t* handle,
}
fd = handle->io_watcher.fd;
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) {
uv__set_sys_error(handle->loop, errno);
err = uv__set_reuse(fd);
if (err) {
uv__set_sys_error(handle->loop, -err);
goto out;
}
/* On the BSDs, SO_REUSEADDR lets you reuse an address that's in the TIME_WAIT
* state (i.e. was until recently tied to a socket) while SO_REUSEPORT lets
* multiple processes bind to the same address. Yes, it's something of a
* misnomer but then again, SO_REUSEADDR was already taken.
*
* None of the above applies to Linux: SO_REUSEADDR implies SO_REUSEPORT on
* Linux and hence it does not have SO_REUSEPORT at all.
*/
#ifndef __linux__
#ifdef SO_REUSEPORT
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) {
uv__set_sys_error(handle->loop, errno);
goto out;
}
#endif
#endif
if (flags & UV_UDP_IPV6ONLY) {
#ifdef IPV6_V6ONLY
yes = 1;
@ -483,7 +491,7 @@ int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags) {
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
int saved_errno;
int status;
int yes;
int err;
saved_errno = errno;
status = -1;
@ -494,28 +502,12 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
goto out;
}
yes = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) {
uv__set_sys_error(handle->loop, errno);
err = uv__set_reuse(sock);
if (err) {
uv__set_sys_error(handle->loop, -err);
goto out;
}
/* On the BSDs, SO_REUSEADDR lets you reuse an address that's in the TIME_WAIT
* state (i.e. was until recently tied to a socket) while SO_REUSEPORT lets
* multiple processes bind to the same address. Yes, it's something of a
* misnomer but then again, SO_REUSEADDR was already taken.
*
* None of the above applies to Linux: SO_REUSEADDR implies SO_REUSEPORT on
* Linux and hence it does not have SO_REUSEPORT at all.
*/
#ifdef SO_REUSEPORT
yes = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof yes) == -1) {
uv__set_sys_error(handle->loop, errno);
goto out;
}
#endif
handle->io_watcher.fd = sock;
status = 0;

View File

@ -34,7 +34,7 @@
#define UV_VERSION_MAJOR 0
#define UV_VERSION_MINOR 10
#define UV_VERSION_PATCH 13
#define UV_VERSION_PATCH 25
#define UV_VERSION_IS_RELEASE 1

View File

@ -339,7 +339,8 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
_snwprintf(filenamew, size, L"%s\\%s", handle->dirw,
_snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw,
file_info->FileNameLength / sizeof(WCHAR),
file_info->FileName);
filenamew[size - 1] = L'\0';

View File

@ -41,33 +41,41 @@
#define QUEUE_FS_TP_JOB(loop, req) \
if (!QueueUserWorkItem(&uv_fs_thread_proc, \
req, \
WT_EXECUTEDEFAULT)) { \
uv__set_sys_error((loop), GetLastError()); \
return -1; \
} \
uv__req_register(loop, req);
do { \
if (!QueueUserWorkItem(&uv_fs_thread_proc, \
req, \
WT_EXECUTEDEFAULT)) { \
uv__set_sys_error((loop), GetLastError()); \
return -1; \
} \
uv__req_register(loop, req); \
} while (0)
#define SET_UV_LAST_ERROR_FROM_REQ(req) \
uv__set_error(req->loop, req->errorno, req->sys_errno_);
uv__set_error(req->loop, req->errorno, req->sys_errno_)
#define SET_REQ_RESULT(req, result_value) \
req->result = (result_value); \
if (req->result == -1) { \
req->sys_errno_ = _doserrno; \
req->errorno = uv_translate_sys_error(req->sys_errno_); \
}
do { \
req->result = (result_value); \
if (req->result == -1) { \
req->sys_errno_ = _doserrno; \
req->errorno = uv_translate_sys_error(req->sys_errno_); \
} \
} while (0)
#define SET_REQ_WIN32_ERROR(req, sys_errno) \
req->result = -1; \
req->sys_errno_ = (sys_errno); \
req->errorno = uv_translate_sys_error(req->sys_errno_);
do { \
req->result = -1; \
req->sys_errno_ = (sys_errno); \
req->errorno = uv_translate_sys_error(req->sys_errno_); \
} while (0)
#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno) \
req->result = -1; \
req->sys_errno_ = (sys_errno); \
req->errorno = (uv_errno);
do { \
req->result = -1; \
req->sys_errno_ = (sys_errno); \
req->errorno = (uv_errno); \
} while (0)
#define VERIFY_FD(fd, req) \
if (fd == -1) { \
@ -78,7 +86,7 @@
}
#define FILETIME_TO_TIME_T(filetime) \
((*((uint64_t*) &(filetime)) - 116444736000000000ULL) / 10000000ULL);
((*((uint64_t*) &(filetime)) - 116444736000000000ULL) / 10000000ULL)
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
do { \
@ -392,7 +400,7 @@ void fs__open(uv_fs_t* req) {
DWORD disposition;
DWORD attributes = 0;
HANDLE file;
int result, current_umask;
int fd, current_umask;
int flags = req->file_flags;
/* Obtain the active umask. umask() never fails and returns the previous */
@ -413,8 +421,7 @@ void fs__open(uv_fs_t* req) {
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
break;
default:
result = -1;
goto end;
goto einval;
}
if (flags & _O_APPEND) {
@ -451,8 +458,7 @@ void fs__open(uv_fs_t* req) {
disposition = CREATE_ALWAYS;
break;
default:
result = -1;
goto end;
goto einval;
}
attributes |= FILE_ATTRIBUTE_NORMAL;
@ -481,8 +487,7 @@ void fs__open(uv_fs_t* req) {
attributes |= FILE_FLAG_RANDOM_ACCESS;
break;
default:
result = -1;
goto end;
goto einval;
}
/* Setting this flag makes it possible to open a directory. */
@ -507,11 +512,30 @@ void fs__open(uv_fs_t* req) {
}
return;
}
result = _open_osfhandle((intptr_t) file, flags);
end:
SET_REQ_RESULT(req, result);
fd = _open_osfhandle((intptr_t) file, flags);
if (fd < 0) {
/* The only known failure mode for _open_osfhandle() is EMFILE, in which
* case GetLastError() will return zero. However we'll try to handle other
* errors as well, should they ever occur.
*/
if (errno == EMFILE)
SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
else if (GetLastError() != ERROR_SUCCESS)
SET_REQ_WIN32_ERROR(req, GetLastError());
else
SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
return;
}
SET_REQ_RESULT(req, fd);
return;
einval:
SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
}
void fs__close(uv_fs_t* req) {
int fd = req->fd;
int result;
@ -1062,7 +1086,6 @@ static void fs__chmod(uv_fs_t* req) {
static void fs__fchmod(uv_fs_t* req) {
int fd = req->fd;
int result;
HANDLE handle;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
@ -1070,7 +1093,7 @@ static void fs__fchmod(uv_fs_t* req) {
VERIFY_FD(fd, req);
handle = (HANDLE)_get_osfhandle(fd);
handle = (HANDLE) _get_osfhandle(fd);
nt_status = pNtQueryInformationFile(handle,
&io_status,
@ -1078,9 +1101,9 @@ static void fs__fchmod(uv_fs_t* req) {
sizeof file_info,
FileBasicInformation);
if (nt_status != STATUS_SUCCESS) {
result = -1;
goto done;
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
return;
}
if (req->mode & _S_IWRITE) {
@ -1095,15 +1118,12 @@ static void fs__fchmod(uv_fs_t* req) {
sizeof file_info,
FileBasicInformation);
if (nt_status != STATUS_SUCCESS) {
result = -1;
goto done;
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
return;
}
result = 0;
done:
SET_REQ_RESULT(req, result);
SET_REQ_SUCCESS(req);
}

View File

@ -1480,6 +1480,13 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
assert(handle->type == UV_NAMED_PIPE);
if (handle->flags & UV__HANDLE_CLOSING) {
/* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
DECREASE_PENDING_REQ_COUNT(handle);
return;
}
if (REQ_SUCCESS(req)) {
assert(req->pipeHandle != INVALID_HANDLE_VALUE);
req->next_pending = handle->pending_accepts;
@ -1528,9 +1535,9 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
UNREGISTER_HANDLE_REQ(loop, handle, req);
/* Initialize and optionally start the eof timer. */
/* This makes no sense if we've already seen EOF. */
if (handle->flags & UV_HANDLE_READABLE) {
/* Initialize and optionally start the eof timer. Only do this if the */
/* pipe is readable and we haven't seen EOF come in ourselves. */
eof_timer_init(handle);
/* If reading start the timer right now. */
@ -1538,6 +1545,12 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
if (handle->flags & UV_HANDLE_READ_PENDING) {
eof_timer_start(handle);
}
} else {
/* This pipe is not readable. We can just close it to let the other end */
/* know that we're done writing. */
CloseHandle(handle->handle);
handle->handle = INVALID_HANDLE_VALUE;
}
if (req->cb) {

View File

@ -104,12 +104,16 @@ static uv_err_t uv__create_stdio_pipe_pair(uv_loop_t* loop,
uv_err_t err;
if (flags & UV_READABLE_PIPE) {
server_access |= PIPE_ACCESS_OUTBOUND;
/* The server needs inbound access too, otherwise CreateNamedPipe() */
/* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */
/* probe the state of the write buffer when we're trying to shutdown */
/* the pipe. */
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
if (flags & UV_WRITABLE_PIPE) {
server_access |= PIPE_ACCESS_INBOUND;
client_access |= GENERIC_WRITE;
client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
}
/* Create server pipe handle. */
@ -163,8 +167,11 @@ static uv_err_t uv__create_stdio_pipe_pair(uv_loop_t* loop,
}
}
/* The server end is now readable and writable. */
server_pipe->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
/* The server end is now readable and/or writable. */
if (flags & UV_READABLE_PIPE)
server_pipe->flags |= UV_HANDLE_WRITABLE;
if (flags & UV_WRITABLE_PIPE)
server_pipe->flags |= UV_HANDLE_READABLE;
*child_pipe_ptr = child_pipe;
return uv_ok_;

View File

@ -577,6 +577,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
req->accept_socket = INVALID_SOCKET;
req->data = handle;
req->wait_handle = INVALID_HANDLE_VALUE;
req->event_handle = NULL;
}
}
@ -1040,9 +1041,11 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (req->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(req->wait_handle);
req->wait_handle = INVALID_HANDLE_VALUE;
}
if (req->event_handle) {
CloseHandle(req->event_handle);
req->event_handle = NULL;
}
}

View File

@ -0,0 +1,108 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#if !defined(_WIN32)
#include "uv.h"
#include "task.h"
#include <errno.h>
#include <stdio.h>
#include <sys/resource.h>
#include <unistd.h>
static void connection_cb(uv_stream_t* server_handle, int status);
static void connect_cb(uv_connect_t* req, int status);
static const int maxfd = 31;
static unsigned connect_cb_called;
static uv_tcp_t server_handle;
static uv_tcp_t client_handle;
TEST_IMPL(emfile) {
struct sockaddr_in addr;
struct rlimit limits;
uv_connect_t connect_req;
uv_loop_t* loop;
int first_fd;
loop = uv_default_loop();
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
ASSERT(0 == uv_tcp_init(loop, &server_handle));
ASSERT(0 == uv_tcp_init(loop, &client_handle));
ASSERT(0 == uv_tcp_bind(&server_handle, addr));
ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb));
/* Lower the file descriptor limit and use up all fds save one. */
limits.rlim_cur = limits.rlim_max = maxfd + 1;
if (setrlimit(RLIMIT_NOFILE, &limits)) {
perror("setrlimit(RLIMIT_NOFILE)");
ASSERT(0);
}
/* Remember the first one so we can clean up afterwards. */
do
first_fd = dup(0);
while (first_fd == -1 && errno == EINTR);
ASSERT(first_fd > 0);
while (dup(0) != -1 || errno == EINTR);
ASSERT(errno == EMFILE);
close(maxfd);
/* Now connect and use up the last available file descriptor. The EMFILE
* handling logic in src/unix/stream.c should ensure that connect_cb() runs
* whereas connection_cb() should *not* run.
*/
ASSERT(0 == uv_tcp_connect(&connect_req, &client_handle, addr, connect_cb));
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
ASSERT(1 == connect_cb_called);
/* Close the dups again. Ignore errors in the unlikely event that the
* file descriptors were not contiguous.
*/
while (first_fd < maxfd) {
close(first_fd);
first_fd += 1;
}
MAKE_VALGRIND_HAPPY();
return 0;
}
static void connection_cb(uv_stream_t* server_handle, int status) {
ASSERT(0 && "connection_cb should not be called.");
}
static void connect_cb(uv_connect_t* req, int status) {
/* |status| should equal 0 because the connection should have been accepted,
* it's just that the server immediately closes it again.
*/
ASSERT(0 == status);
connect_cb_called += 1;
uv_close((uv_handle_t*) &server_handle, NULL);
uv_close((uv_handle_t*) &client_handle, NULL);
}
#endif /* !defined(_WIN32) */

View File

@ -439,7 +439,7 @@ static void on_tcp_child_process_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t
return;
}
printf("error recving on tcp connection: %s\n",
printf("error recving on tcp connection: %s\n",
uv_strerror(uv_last_error(tcp->loop)));
abort();
}

View File

@ -64,6 +64,7 @@ TEST_DECLARE (tcp_connect_error_fault)
TEST_DECLARE (tcp_connect_timeout)
TEST_DECLARE (tcp_close_while_connecting)
TEST_DECLARE (tcp_close)
TEST_DECLARE (tcp_close_accept)
TEST_DECLARE (tcp_flags)
TEST_DECLARE (tcp_write_to_half_open_connection)
TEST_DECLARE (tcp_unexpected_read)
@ -87,11 +88,13 @@ TEST_DECLARE (pipe_bind_error_inval)
TEST_DECLARE (pipe_listen_without_bind)
TEST_DECLARE (pipe_connect_bad_name)
TEST_DECLARE (pipe_connect_to_file)
TEST_DECLARE (pipe_server_close)
TEST_DECLARE (connection_fail)
TEST_DECLARE (connection_fail_doesnt_auto_close)
TEST_DECLARE (shutdown_close_tcp)
TEST_DECLARE (shutdown_close_pipe)
TEST_DECLARE (shutdown_eof)
TEST_DECLARE (shutdown_twice)
TEST_DECLARE (callback_stack)
TEST_DECLARE (error_message)
TEST_DECLARE (timer)
@ -106,6 +109,7 @@ TEST_DECLARE (idle_starvation)
TEST_DECLARE (loop_handles)
TEST_DECLARE (get_loadavg)
TEST_DECLARE (walk_handles)
TEST_DECLARE (watcher_cross_stop)
TEST_DECLARE (ref)
TEST_DECLARE (idle_ref)
TEST_DECLARE (async_ref)
@ -157,6 +161,7 @@ TEST_DECLARE (spawn_preserve_env)
TEST_DECLARE (spawn_setuid_fails)
TEST_DECLARE (spawn_setgid_fails)
TEST_DECLARE (spawn_stdout_to_file)
TEST_DECLARE (spawn_stdout_and_stderr_to_file)
TEST_DECLARE (spawn_auto_unref)
TEST_DECLARE (fs_poll)
TEST_DECLARE (kill)
@ -216,6 +221,7 @@ TEST_DECLARE (listen_with_simultaneous_accepts)
TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
#else
TEST_DECLARE (emfile)
TEST_DECLARE (spawn_setuid_setgid)
TEST_DECLARE (we_get_signal)
TEST_DECLARE (we_get_signals)
@ -254,6 +260,7 @@ TASK_LIST_START
TEST_ENTRY (pipe_connect_bad_name)
TEST_ENTRY (pipe_connect_to_file)
TEST_ENTRY (pipe_server_close)
TEST_ENTRY (tty)
TEST_ENTRY (stdio_over_pipes)
TEST_ENTRY (ipc_listen_before_write)
@ -297,6 +304,7 @@ TASK_LIST_START
TEST_ENTRY (tcp_connect_timeout)
TEST_ENTRY (tcp_close_while_connecting)
TEST_ENTRY (tcp_close)
TEST_ENTRY (tcp_close_accept)
TEST_ENTRY (tcp_flags)
TEST_ENTRY (tcp_write_to_half_open_connection)
TEST_ENTRY (tcp_unexpected_read)
@ -337,6 +345,9 @@ TASK_LIST_START
TEST_ENTRY (shutdown_eof)
TEST_HELPER (shutdown_eof, tcp4_echo_server)
TEST_ENTRY (shutdown_twice)
TEST_HELPER (shutdown_twice, tcp4_echo_server)
TEST_ENTRY (callback_stack)
TEST_HELPER (callback_stack, tcp4_echo_server)
@ -385,6 +396,8 @@ TASK_LIST_START
TEST_ENTRY (loop_handles)
TEST_ENTRY (walk_handles)
TEST_ENTRY (watcher_cross_stop)
TEST_ENTRY (active)
TEST_ENTRY (embed)
@ -427,6 +440,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_setuid_fails)
TEST_ENTRY (spawn_setgid_fails)
TEST_ENTRY (spawn_stdout_to_file)
TEST_ENTRY (spawn_stdout_and_stderr_to_file)
TEST_ENTRY (spawn_auto_unref)
TEST_ENTRY (fs_poll)
TEST_ENTRY (kill)
@ -439,6 +453,7 @@ TASK_LIST_START
TEST_ENTRY (listen_no_simultaneous_accepts)
TEST_ENTRY (fs_stat_root)
#else
TEST_ENTRY (emfile)
TEST_ENTRY (spawn_setuid_setgid)
TEST_ENTRY (we_get_signal)
TEST_ENTRY (we_get_signals)

View File

@ -0,0 +1,91 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <string.h>
#include <errno.h>
static uv_pipe_t pipe_client;
static uv_pipe_t pipe_server;
static uv_connect_t connect_req;
static int pipe_close_cb_called = 0;
static int pipe_client_connect_cb_called = 0;
static void pipe_close_cb(uv_handle_t* handle) {
ASSERT(handle == (uv_handle_t*) &pipe_client ||
handle == (uv_handle_t*) &pipe_server);
pipe_close_cb_called++;
}
static void pipe_client_connect_cb(uv_connect_t* req, int status) {
ASSERT(req == &connect_req);
ASSERT(status == 0);
pipe_client_connect_cb_called++;
uv_close((uv_handle_t*) &pipe_client, pipe_close_cb);
uv_close((uv_handle_t*) &pipe_server, pipe_close_cb);
}
static void pipe_server_connection_cb(uv_stream_t* handle, int status) {
/* This function *may* be called, depending on whether accept or the
* connection callback is called first.
*/
ASSERT(status == 0);
}
TEST_IMPL(pipe_server_close) {
uv_loop_t* loop;
int r;
loop = uv_default_loop();
ASSERT(loop != NULL);
r = uv_pipe_init(loop, &pipe_server, 0);
ASSERT(r == 0);
r = uv_pipe_bind(&pipe_server, TEST_PIPENAME);
ASSERT(r == 0);
r = uv_listen((uv_stream_t*) &pipe_server, 0, pipe_server_connection_cb);
ASSERT(r == 0);
r = uv_pipe_init(loop, &pipe_client, 0);
ASSERT(r == 0);
uv_pipe_connect(&connect_req, &pipe_client, TEST_PIPENAME, pipe_client_connect_cb);
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(pipe_client_connect_cb_called == 1);
ASSERT(pipe_close_cb_called == 2);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -59,7 +59,7 @@ TEST_IMPL(poll_close) {
uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]);
uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL);
}
for (i = 0; i < NUM_SOCKETS; i++) {
uv_close((uv_handle_t*) &poll_handles[i], close_cb);
}

View File

@ -0,0 +1,83 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/*
* This is a regression test for issue #1113 (calling uv_shutdown twice will
* leave a ghost request in the system)
*/
#include "uv.h"
#include "task.h"
static uv_shutdown_t req1;
static uv_shutdown_t req2;
static int shutdown_cb_called = 0;
static void close_cb(uv_handle_t* handle) {
}
static void shutdown_cb(uv_shutdown_t* req, int status) {
ASSERT(req == &req1);
ASSERT(status == 0);
shutdown_cb_called++;
uv_close((uv_handle_t*) req->handle, close_cb);
}
static void connect_cb(uv_connect_t* req, int status) {
int r;
ASSERT(status == 0);
r = uv_shutdown(&req1, req->handle, shutdown_cb);
ASSERT(r == 0);
r = uv_shutdown(&req2, req->handle, shutdown_cb);
ASSERT(r != 0);
}
TEST_IMPL(shutdown_twice) {
struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
uv_loop_t* loop;
int r;
uv_tcp_t h;
uv_connect_t connect_req;
loop = uv_default_loop();
r = uv_tcp_init(loop, &h);
r = uv_tcp_connect(&connect_req,
&h,
addr,
connect_cb);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(shutdown_cb_called == 1);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -263,6 +263,61 @@ TEST_IMPL(spawn_stdout_to_file) {
}
TEST_IMPL(spawn_stdout_and_stderr_to_file) {
int r;
uv_file file;
uv_fs_t fs_req;
uv_stdio_container_t stdio[3];
/* Setup. */
unlink("stdout_file");
init_process_options("spawn_helper6", exit_cb);
r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
S_IREAD | S_IWRITE, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&fs_req);
file = r;
options.stdio = stdio;
options.stdio[0].flags = UV_IGNORE;
options.stdio[1].flags = UV_INHERIT_FD;
options.stdio[1].data.fd = file;
options.stdio[2].flags = UV_INHERIT_FD;
options.stdio[2].data.fd = file;
options.stdio_count = 3;
r = uv_spawn(uv_default_loop(), &process, options);
ASSERT(r == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 1);
r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
0, NULL);
ASSERT(r == 27);
uv_fs_req_cleanup(&fs_req);
r = uv_fs_close(uv_default_loop(), &fs_req, file, NULL);
ASSERT(r == 0);
uv_fs_req_cleanup(&fs_req);
printf("output is: %s", output);
ASSERT(strcmp("hello world\nhello errworld\n", output) == 0);
/* Cleanup. */
unlink("stdout_file");
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(spawn_stdin) {
int r;
uv_pipe_t out;
@ -562,6 +617,53 @@ TEST_IMPL(spawn_and_ping) {
}
TEST_IMPL(spawn_same_stdout_stderr) {
uv_write_t write_req;
uv_pipe_t in, out;
uv_buf_t buf;
uv_stdio_container_t stdio[3];
int r;
init_process_options("spawn_helper3", exit_cb);
buf = uv_buf_init("TEST", 4);
uv_pipe_init(uv_default_loop(), &out, 0);
uv_pipe_init(uv_default_loop(), &in, 0);
options.stdio = stdio;
options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
options.stdio[0].data.stream = (uv_stream_t*)&in;
options.stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
options.stdio[1].data.stream = (uv_stream_t*)&out;
options.stdio_count = 2;
r = uv_spawn(uv_default_loop(), &process, options);
ASSERT(r == 0);
/* Sending signum == 0 should check if the
* child process is still alive, not kill it.
*/
r = uv_process_kill(&process, 0);
ASSERT(r == 0);
r = uv_write(&write_req, (uv_stream_t*)&in, &buf, 1, write_cb);
ASSERT(r == 0);
r = uv_read_start((uv_stream_t*)&out, on_alloc, on_read);
ASSERT(r == 0);
ASSERT(exit_cb_called == 0);
r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(exit_cb_called == 1);
ASSERT(strcmp(output, "TEST") == 0);
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(kill) {
int r;
uv_err_t err;

View File

@ -0,0 +1,177 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <stdio.h>
#include <string.h>
static struct sockaddr_in addr;
static uv_tcp_t tcp_server;
static uv_tcp_t tcp_outgoing[2];
static uv_tcp_t tcp_incoming[ARRAY_SIZE(tcp_outgoing)];
static uv_connect_t connect_reqs[ARRAY_SIZE(tcp_outgoing)];
static uv_tcp_t tcp_check;
static uv_connect_t tcp_check_req;
static uv_write_t write_reqs[ARRAY_SIZE(tcp_outgoing)];
static unsigned int got_connections;
static unsigned int close_cb_called;
static unsigned int write_cb_called;
static unsigned int read_cb_called;
static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
static void write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
write_cb_called++;
}
static void connect_cb(uv_connect_t* req, int status) {
unsigned int i;
uv_buf_t buf;
uv_stream_t* outgoing;
if (req == &tcp_check_req) {
ASSERT(status != 0);
/* Close check and incoming[0], time to finish test */
uv_close((uv_handle_t*) &tcp_incoming[0], close_cb);
uv_close((uv_handle_t*) &tcp_check, close_cb);
return;
}
ASSERT(status == 0);
ASSERT(connect_reqs <= req);
ASSERT(req <= connect_reqs + ARRAY_SIZE(connect_reqs));
i = req - connect_reqs;
buf = uv_buf_init("x", 1);
outgoing = (uv_stream_t*) &tcp_outgoing[i];
ASSERT(0 == uv_write(&write_reqs[i], outgoing, &buf, 1, write_cb));
}
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
static char buf[1];
return uv_buf_init(buf, sizeof(buf));
}
static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t b) {
uv_loop_t* loop;
unsigned int i;
/* Only first stream should receive read events */
ASSERT(stream == (uv_stream_t*) &tcp_incoming[0]);
ASSERT(0 == uv_read_stop(stream));
ASSERT(1 == nread);
loop = stream->loop;
read_cb_called++;
/* Close all active incomings, except current one */
for (i = 1; i < got_connections; i++)
uv_close((uv_handle_t*) &tcp_incoming[i], close_cb);
/* Create new fd that should be one of the closed incomings */
ASSERT(0 == uv_tcp_init(loop, &tcp_check));
ASSERT(0 == uv_tcp_connect(&tcp_check_req, &tcp_check, addr, connect_cb));
ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_check, alloc_cb, read_cb));
/* Close server, so no one will connect to it */
uv_close((uv_handle_t*) &tcp_server, close_cb);
}
static void connection_cb(uv_stream_t* server, int status) {
unsigned int i;
uv_tcp_t* incoming;
ASSERT(server == (uv_stream_t*) &tcp_server);
/* Ignore tcp_check connection */
if (got_connections == ARRAY_SIZE(tcp_incoming))
return;
/* Accept everyone */
incoming = &tcp_incoming[got_connections++];
ASSERT(0 == uv_tcp_init(server->loop, incoming));
ASSERT(0 == uv_accept(server, (uv_stream_t*) incoming));
if (got_connections != ARRAY_SIZE(tcp_incoming))
return;
/* Once all clients are accepted - start reading */
for (i = 0; i < ARRAY_SIZE(tcp_incoming); i++) {
incoming = &tcp_incoming[i];
ASSERT(0 == uv_read_start((uv_stream_t*) incoming, alloc_cb, read_cb));
}
}
TEST_IMPL(tcp_close_accept) {
unsigned int i;
uv_loop_t* loop;
uv_tcp_t* client;
/*
* A little explanation of what goes on below:
*
* We'll create server and connect to it using two clients, each writing one
* byte once connected.
*
* When all clients will be accepted by server - we'll start reading from them
* and, on first client's first byte, will close second client and server.
* After that, we'll immediately initiate new connection to server using
* tcp_check handle (thus, reusing fd from second client).
*
* In this situation uv__io_poll()'s event list should still contain read
* event for second client, and, if not cleaned up properly, `tcp_check` will
* receive stale event of second incoming and invoke `connect_cb` with zero
* status.
*/
loop = uv_default_loop();
addr = uv_ip4_addr("0.0.0.0", TEST_PORT);
ASSERT(0 == uv_tcp_init(loop, &tcp_server));
ASSERT(0 == uv_tcp_bind(&tcp_server, addr));
ASSERT(0 == uv_listen((uv_stream_t*) &tcp_server,
ARRAY_SIZE(tcp_outgoing),
connection_cb));
for (i = 0; i < ARRAY_SIZE(tcp_outgoing); i++) {
client = tcp_outgoing + i;
ASSERT(0 == uv_tcp_init(loop, client));
ASSERT(0 == uv_tcp_connect(&connect_reqs[i], client, addr, connect_cb));
}
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(ARRAY_SIZE(tcp_outgoing) == got_connections);
ASSERT((ARRAY_SIZE(tcp_outgoing) + 2) == close_cb_called);
ASSERT(ARRAY_SIZE(tcp_outgoing) == write_cb_called);
ASSERT(1 == read_cb_called);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -0,0 +1,108 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
#include <string.h>
#include <errno.h>
#if !defined(_WIN32)
#include <sys/time.h>
#include <sys/resource.h> /* setrlimit() */
#endif
/* NOTE: Number should be big enough to trigger this problem */
static uv_udp_t sockets[2500];
static uv_udp_send_t reqs[ARRAY_SIZE(sockets)];
static char buf[1];
static unsigned int recv_cb_called;
static unsigned int send_cb_called;
static unsigned int close_cb_called;
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
return uv_buf_init(buf, sizeof(buf));
}
static void recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
recv_cb_called++;
}
static void send_cb(uv_udp_send_t* req, int status) {
send_cb_called++;
}
static void close_cb(uv_handle_t* handle) {
close_cb_called++;
}
TEST_IMPL(watcher_cross_stop) {
uv_loop_t* loop = uv_default_loop();
unsigned int i;
struct sockaddr_in addr;
uv_buf_t buf;
char big_string[1024];
#if !defined(_WIN32)
{
struct rlimit lim;
lim.rlim_cur = ARRAY_SIZE(sockets) + 32;
lim.rlim_max = ARRAY_SIZE(sockets) + 32;
if (setrlimit(RLIMIT_NOFILE, &lim))
RETURN_SKIP("File descriptor limit too low.");
}
#endif
addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
memset(big_string, 'A', sizeof(big_string));
buf = uv_buf_init(big_string, sizeof(big_string));
for (i = 0; i < ARRAY_SIZE(sockets); i++) {
ASSERT(0 == uv_udp_init(loop, &sockets[i]));
ASSERT(0 == uv_udp_bind(&sockets[i], addr, 0));
ASSERT(0 == uv_udp_recv_start(&sockets[i], alloc_cb, recv_cb));
ASSERT(0 == uv_udp_send(&reqs[i], &sockets[i], &buf, 1, addr, send_cb));
}
while (recv_cb_called == 0)
uv_run(loop, UV_RUN_ONCE);
for (i = 0; i < ARRAY_SIZE(sockets); i++)
uv_close((uv_handle_t*) &sockets[i], close_cb);
ASSERT(0 < recv_cb_called && recv_cb_called <= ARRAY_SIZE(sockets));
ASSERT(ARRAY_SIZE(sockets) == send_cb_called);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(ARRAY_SIZE(sockets) == close_cb_called);
MAKE_VALGRIND_HAPPY();
return 0;
}

View File

@ -295,6 +295,7 @@
'test/test-delayed-accept.c',
'test/test-error.c',
'test/test-embed.c',
'test/test-emfile.c',
'test/test-fail-always.c',
'test/test-fs.c',
'test/test-fs-event.c',
@ -310,12 +311,14 @@
'test/test-loop-handles.c',
'test/test-loop-stop.c',
'test/test-walk-handles.c',
'test/test-watcher-cross-stop.c',
'test/test-multiple-listen.c',
'test/test-osx-select.c',
'test/test-pass-always.c',
'test/test-ping-pong.c',
'test/test-pipe-bind-error.c',
'test/test-pipe-connect-error.c',
'test/test-pipe-server-close.c',
'test/test-platform-output.c',
'test/test-poll.c',
'test/test-poll-close.c',
@ -326,6 +329,7 @@
'test/test-semaphore.c',
'test/test-shutdown-close.c',
'test/test-shutdown-eof.c',
'test/test-shutdown-twice.c',
'test/test-signal.c',
'test/test-signal-multiple-loops.c',
'test/test-spawn.c',
@ -334,6 +338,7 @@
'test/test-tcp-bind-error.c',
'test/test-tcp-bind6-error.c',
'test/test-tcp-close.c',
'test/test-tcp-close-accept.c',
'test/test-tcp-close-while-connecting.c',
'test/test-tcp-connect-error-after-write.c',
'test/test-tcp-shutdown-after-write.c',

View File

@ -91,7 +91,7 @@ exit /b 1
:have_gyp
if not defined PYTHON set PYTHON="python"
%PYTHON% gyp_uv -Dtarget_arch=%target_arch% -Dlibrary=%library%
%PYTHON% gyp_uv.py -Dtarget_arch=%target_arch% -Dlibrary=%library%
if errorlevel 1 goto create-msvs-files-failed
if not exist uv.sln goto create-msvs-files-failed
echo Project files generated.

View File

@ -28,7 +28,7 @@
static uv_buf_t
_ames_alloc(uv_handle_t* had_u, size_t len_i)
{
void* ptr_v = malloc(len_i);
void* ptr_v = c3_malloc(len_i);
// uL(fprintf(uH, "grab %p\n", ptr_v));
return uv_buf_init(ptr_v, len_i);
@ -181,7 +181,7 @@ u2_ames_ef_send(u2_noun lan, u2_noun pac)
if ( u2_yes == _ames_lane_ip(lan, &por_s, &pip_w) ) {
c3_w len_w = u2_cr_met(3, pac);
c3_y* buf_y = malloc(len_w);
c3_y* buf_y = c3_malloc(len_w);
u2_cr_bytes(0, len_w, buf_y, pac);
@ -200,7 +200,7 @@ u2_ames_ef_send(u2_noun lan, u2_noun pac)
if ( 0 != pip_w ) {
uv_buf_t buf_u = uv_buf_init((c3_c*)buf_y, len_w);
_u2_udp_send_t* ruq_u = malloc(sizeof(_u2_udp_send_t));
_u2_udp_send_t* ruq_u = c3_malloc(sizeof(_u2_udp_send_t));
ruq_u->buf_y = buf_y;

View File

@ -47,7 +47,7 @@
static uv_buf_t
_cttp_alloc(uv_handle_t* had_u, size_t len_i)
{
return uv_buf_init(malloc(len_i), len_i);
return uv_buf_init(c3_malloc(len_i), len_i);
}
/* _cttp_bod(): create a data buffer.
@ -55,7 +55,7 @@ _cttp_alloc(uv_handle_t* had_u, size_t len_i)
static u2_hbod*
_cttp_bod(c3_w len_w, const c3_y* hun_y)
{
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
bod_u->len_w = len_w;
memcpy(bod_u->hun_y, hun_y, len_w);
@ -72,7 +72,7 @@ _cttp_bud(c3_c* nam_c, c3_c* val_c)
c3_w lnm_w = strlen(nam_c);
c3_w lvl_w = strlen(val_c);
c3_w len_w = lnm_w + 2 + lvl_w + 2;
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
strncpy((c3_c *)bod_u->hun_y, nam_c, lnm_w);
strncpy((c3_c *)bod_u->hun_y + lnm_w, ": ", 2);
@ -145,7 +145,7 @@ _cttp_bods_to_octs(u2_hbod* bod_u)
len_w += bid_u->len_w;
}
}
buf_y = malloc(len_w);
buf_y = c3_malloc(len_w);
{
c3_y* ptr_y = buf_y;
@ -171,7 +171,7 @@ _cttp_heds_list(u2_hhed* hed_u, u2_noun nam, u2_noun vaz)
while ( u2_nul != viz ) {
u2_hhed* deh_u;
deh_u = malloc(sizeof(*deh_u));
deh_u = c3_malloc(sizeof(*deh_u));
deh_u->nam_c = u2_cr_string(nam);
deh_u->val_c = u2_cr_string(u2h(viz));
@ -222,7 +222,7 @@ _cttp_octs_to_bod(u2_noun oct)
len_w = u2h(oct);
{
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
bod_u->len_w = len_w;
u2_cr_bytes(0, len_w, bod_u->hun_y, u2t(oct));
@ -414,7 +414,7 @@ static c3_c*
_cttp_creq_url(u2_noun pul)
{
c3_w len_w = _cttp_mcut_url(0, 0, u2k(pul));
c3_c* url_c = malloc(len_w + 1);
c3_c* url_c = c3_malloc(len_w + 1);
_cttp_mcut_url(url_c, 0, pul);
url_c[len_w] = 0;
@ -428,7 +428,7 @@ static c3_c*
_cttp_creq_host(u2_noun hot)
{
c3_w len_w = _cttp_mcut_host(0, 0, u2k(hot));
c3_c* hot_c = malloc(len_w + 1);
c3_c* hot_c = c3_malloc(len_w + 1);
_cttp_mcut_host(hot_c, 0, hot);
hot_c[len_w] = 0;
@ -508,7 +508,7 @@ static c3_c*
_cttp_more(c3_c* str_c, const c3_c* buf_c, size_t siz_i)
{
if ( !str_c ) {
str_c = malloc(siz_i + 1);
str_c = c3_malloc(siz_i + 1);
memcpy(str_c, buf_c, siz_i);
str_c[siz_i] = 0;
}
@ -542,7 +542,7 @@ _cttp_header_field(http_parser* par_u, const c3_c* buf_c, size_t siz_i)
switch ( res_u->rat_e ) {
case u2_hreq_non:
case u2_hreq_val: {
u2_hhed* hed_u = malloc(sizeof(*hed_u));
u2_hhed* hed_u = c3_malloc(sizeof(*hed_u));
hed_u->nam_c = _cttp_more(0, buf_c, siz_i);
hed_u->val_c = 0;
@ -662,12 +662,12 @@ static struct http_parser_settings _cttp_settings = {
static void
_cttp_cres_start(u2_creq* ceq_u)
{
u2_cres* res_u = malloc(sizeof(*res_u));
u2_cres* res_u = c3_malloc(sizeof(*res_u));
memset(res_u, 0, sizeof(*res_u));
ceq_u->res_u = res_u;
res_u->par_u = malloc(sizeof(struct http_parser));
res_u->par_u = c3_malloc(sizeof(struct http_parser));
http_parser_init(res_u->par_u, HTTP_RESPONSE);
((struct http_parser *)(res_u->par_u))->data = ceq_u;
@ -990,7 +990,7 @@ _cttp_ccon_kick_write_cryp(u2_ccon* coc_u)
static void
_cttp_ccon_kick_write_buf(u2_ccon* coc_u, uv_buf_t buf_u)
{
_u2_write_t* ruq_u = (_u2_write_t*) malloc(sizeof(_u2_write_t));
_u2_write_t* ruq_u = (_u2_write_t*) c3_malloc(sizeof(_u2_write_t));
ruq_u->coc_u = coc_u;
ruq_u->buf_y = (c3_y*)buf_u.base;
@ -1014,7 +1014,7 @@ _cttp_ccon_kick_write_body(u2_ccon* coc_u, u2_hbod *rub_u)
// XX extra copy here due to old code. Use hbod as base directly.
//
{
c3_y* buf_y = malloc(rub_u->len_w + 1);
c3_y* buf_y = c3_malloc(rub_u->len_w + 1);
memcpy(buf_y, rub_u->hun_y, rub_u->len_w);
buf_y[rub_u->len_w] = 0;
@ -1051,7 +1051,7 @@ _cttp_ccon_cryp_rout(u2_ccon* coc_u)
c3_i bur_i;
{
c3_y* buf_y = malloc(1<<14);
c3_y* buf_y = c3_malloc(1<<14);
while ( 0 < (bur_i = BIO_read(coc_u->ssl.wio_u, buf_y, 1<<14)) ) {
buf_u = uv_buf_init((c3_c*)buf_y, bur_i);
_cttp_ccon_kick_write_buf(coc_u, buf_u);
@ -1298,7 +1298,7 @@ _cttp_ccon_kick(u2_ccon* coc_u)
static u2_ccon*
_cttp_ccon_new(u2_bean sec, c3_s por_s, c3_c* hot_c)
{
u2_ccon* coc_u = malloc(sizeof(u2_ccon));
u2_ccon* coc_u = c3_malloc(sizeof(u2_ccon));
memset(coc_u, 0, sizeof(u2_ccon));
@ -1354,7 +1354,7 @@ _cttp_ccon(u2_bean sec, c3_s por_s, c3_c* hot_c)
static u2_creq*
_cttp_creq_new(c3_l num_l, u2_noun hes)
{
u2_creq* ceq_u = malloc(sizeof(u2_creq));
u2_creq* ceq_u = c3_malloc(sizeof(u2_creq));
u2_noun pul = u2h(hes);
u2_noun hat = u2h(pul);
u2_noun sec = u2h(hat);

View File

@ -31,7 +31,7 @@ static void _http_conn_dead(u2_hcon *hon_u);
static uv_buf_t
_http_alloc(uv_handle_t* had_u, size_t len_i)
{
return uv_buf_init(malloc(len_i), len_i);
return uv_buf_init(c3_malloc(len_i), len_i);
}
/* _http_bod(): create a data buffer.
@ -39,7 +39,7 @@ _http_alloc(uv_handle_t* had_u, size_t len_i)
static u2_hbod*
_http_bod(c3_w len_w, const c3_y* hun_y)
{
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
bod_u->len_w = len_w;
memcpy(bod_u->hun_y, hun_y, len_w);
@ -56,7 +56,7 @@ _http_bud(c3_c* nam_c, c3_c* val_c)
c3_w lnm_w = strlen(nam_c);
c3_w lvl_w = strlen(val_c);
c3_w len_w = lnm_w + 2 + lvl_w + 2;
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
strncpy((c3_c *)bod_u->hun_y, nam_c, lnm_w);
strncpy((c3_c *)bod_u->hun_y + lnm_w, ": ", 2);
@ -150,7 +150,7 @@ _http_respond_buf(u2_hreq* req_u, uv_buf_t buf_u)
return;
}
ruq_u = (_u2_write_t*) malloc(sizeof(_u2_write_t));
ruq_u = (_u2_write_t*) c3_malloc(sizeof(_u2_write_t));
ruq_u->buf_y = (c3_y*)buf_u.base;
@ -175,7 +175,7 @@ _http_send_body(u2_hreq *req_u,
// XX extra copy here due to old code. Use hbod as base directly.
//
{
c3_y* buf_y = malloc(rub_u->len_w);
c3_y* buf_y = c3_malloc(rub_u->len_w);
memcpy(buf_y, rub_u->hun_y, rub_u->len_w);
buf_u = uv_buf_init((c3_c*)buf_y, rub_u->len_w);
@ -350,7 +350,7 @@ static c3_c*
_http_more(c3_c* str_c, const c3_c* buf_c, size_t siz_i)
{
if ( !str_c ) {
str_c = malloc(siz_i + 1);
str_c = c3_malloc(siz_i + 1);
memcpy(str_c, buf_c, siz_i);
str_c[siz_i] = 0;
}
@ -385,7 +385,7 @@ _http_header_field(http_parser* par_u, const c3_c* buf_c, size_t siz_i)
switch ( req_u->rat_e ) {
case u2_hreq_non:
case u2_hreq_val: {
u2_hhed* hed_u = malloc(sizeof(*hed_u));
u2_hhed* hed_u = c3_malloc(sizeof(*hed_u));
hed_u->nam_c = _http_more(0, buf_c, siz_i);
hed_u->val_c = 0;
@ -508,7 +508,7 @@ static struct http_parser_settings _http_settings = {
static u2_hreq*
_http_req_new(u2_hcon* hon_u)
{
u2_hreq* req_u = malloc(sizeof(*req_u));
u2_hreq* req_u = c3_malloc(sizeof(*req_u));
req_u->hon_u = hon_u;
req_u->seq_l = hon_u->seq_l++;
@ -516,7 +516,7 @@ _http_req_new(u2_hcon* hon_u)
req_u->met_e = (u2_hmet)0;
req_u->rat_e = (u2_hrat)0;
req_u->par_u = malloc(sizeof(struct http_parser));
req_u->par_u = c3_malloc(sizeof(struct http_parser));
http_parser_init(req_u->par_u, HTTP_REQUEST);
((struct http_parser *)(req_u->par_u))->data = req_u;
@ -591,7 +591,7 @@ _http_conn_read_cb(uv_stream_t* tcp_u,
static void
_http_conn_new(u2_http *htp_u)
{
u2_hcon *hon_u = malloc(sizeof(*hon_u));
u2_hcon *hon_u = c3_malloc(sizeof(*hon_u));
uv_tcp_init(u2L, &hon_u->wax_u);
@ -707,7 +707,7 @@ _http_list_to_heds(u2_noun lix)
u2_noun pi_lix = u2h(i_lix);
u2_noun qi_lix = u2t(i_lix);
u2_noun t_lix = u2t(lix);
u2_hhed* nex_u = malloc(sizeof(u2_hhed));
u2_hhed* nex_u = c3_malloc(sizeof(u2_hhed));
nex_u->nam_c = u2_cr_string(pi_lix);
nex_u->val_c = u2_cr_string(qi_lix);
@ -738,7 +738,7 @@ _http_bods_to_octs(u2_hbod* bod_u)
len_w += bid_u->len_w;
}
}
buf_y = malloc(len_w);
buf_y = c3_malloc(len_w);
{
c3_y* ptr_y = buf_y;
@ -768,7 +768,7 @@ _http_octs_to_bod(u2_noun oct)
len_w = u2h(oct);
{
u2_hbod* bod_u = malloc(len_w + sizeof(*bod_u));
u2_hbod* bod_u = c3_malloc(len_w + sizeof(*bod_u));
bod_u->len_w = len_w;
u2_cr_bytes(0, len_w, bod_u->hun_y, u2t(oct));
@ -826,7 +826,7 @@ _http_new_response(c3_l sev_l, c3_l coq_l, c3_l seq_l, u2_noun rep)
return 0;
}
else {
u2_hrep* rep_u = malloc(sizeof(u2_hrep));
u2_hrep* rep_u = c3_malloc(sizeof(u2_hrep));
rep_u->sev_l = sev_l;
rep_u->coq_l = coq_l;
@ -912,6 +912,7 @@ _http_respond(u2_hrep* rep_u)
if ( !(htp_u = _http_serv_find(rep_u->sev_l)) ) {
uL(fprintf(uH, "http: server not found: %d\r\n", rep_u->sev_l));
return;
}
if ( !(hon_u = _http_conn_find(htp_u, rep_u->coq_l)) ) {
uL(fprintf(uH, "http: connection not found: %d\r\n", rep_u->coq_l));
@ -1020,7 +1021,7 @@ u2_http_io_init()
{
// Logically secure port.
{
u2_http *htp_u = malloc(sizeof(*htp_u));
u2_http *htp_u = c3_malloc(sizeof(*htp_u));
htp_u->sev_l = u2A->sev_l + 1;
htp_u->coq_l = 1;
@ -1037,7 +1038,7 @@ u2_http_io_init()
// Insecure port.
//
{
u2_http *htp_u = malloc(sizeof(*htp_u));
u2_http *htp_u = c3_malloc(sizeof(*htp_u));
htp_u->sev_l = u2A->sev_l;
htp_u->coq_l = 1;

View File

@ -65,19 +65,25 @@ _main_getopt(c3_i argc, c3_c** argv)
u2_Host.ops_u.gab = u2_no;
u2_Host.ops_u.loh = u2_no;
u2_Host.ops_u.dem = u2_no;
u2_Host.ops_u.fog = u2_no;
u2_Host.ops_u.pro = u2_no;
u2_Host.ops_u.veb = u2_yes;
u2_Host.ops_u.rez = u2_no;
u2_Host.ops_u.nuu = u2_no;
u2_Host.ops_u.vno = u2_no;
u2_Host.ops_u.kno_w = DefaultKernel;
while ( (ch_i = getopt(argc, argv, "I:f:h:k:l:n:p:r:Labcdgqv")) != -1 ) {
while ( (ch_i = getopt(argc, argv, "I:X:f:h:k:l:n:p:r:Labcdgqv")) != -1 ) {
switch ( ch_i ) {
case 'I': {
u2_Host.ops_u.imp_c = strdup(optarg);
break;
}
case 'X': {
if ( 0 != strcmp("wtf", optarg) ) {
return u2_no;
} else u2_Host.ops_u.fog = u2_yes;
break;
}
case 'f': {
if ( u2_no == _main_readw(optarg, 100, &u2_Host.ops_u.fuz_w) ) {
return u2_no;
@ -151,7 +157,7 @@ _main_getopt(c3_i argc, c3_c** argv)
fprintf(stderr, "$URBIT_HOME or $HOME must be set\n");
exit(1);
} else {
u2_Host.ops_u.hom_c = malloc(hom_w + 1);
u2_Host.ops_u.hom_c = c3_malloc(hom_w + 1);
snprintf(u2_Host.ops_u.hom_c, hom_w + 1, "%s/urbit", hom_c);
}
}
@ -174,7 +180,7 @@ _main_getopt(c3_i argc, c3_c** argv)
if ( u2_Host.ops_u.nam_c == 0 ) {
c3_w len_w = sysconf(_SC_HOST_NAME_MAX) + 1;
u2_Host.ops_u.nam_c = malloc(len_w);
u2_Host.ops_u.nam_c = c3_malloc(len_w);
if ( 0 != gethostname(u2_Host.ops_u.nam_c, len_w) ) {
perror("gethostname");
exit(1);
@ -250,6 +256,16 @@ static void _main_cont(void *arg1, void *arg2, void *arg3)
siglongjmp(Signal_buf, 1);
}
void*
c3_malloc(size_t s)
{
void* rut = malloc(s);
if ( u2_nul == rut ) {
c3_assert(!"memory lost");
}
return rut;
}
static void
overflow_handler(int emergency, stackoverflow_context_t scp)
{
@ -296,7 +312,6 @@ main(c3_i argc,
u2_wr_check_init(u2_Host.ops_u.cpu_c);
if ( (u2_no == u2_Host.ops_u.nuu) &&
(u2_no == u2_Host.ops_u.rez) &&
(u2_yes == u2_loom_load()) )
{
u2_Host.wir_r = u2_ray_of(0, 0);

View File

@ -80,7 +80,7 @@ _raft_readname(const c3_c* str_c, c3_w siz_w)
c3_c* col_c;
c3_w nam_w;
nam_u->str_c = malloc(siz_w + 1);
nam_u->str_c = c3_malloc(siz_w + 1);
strncpy(nam_u->str_c, str_c, siz_w);
nam_u->str_c[siz_w] = '\0';
@ -91,7 +91,7 @@ _raft_readname(const c3_c* str_c, c3_w siz_w)
}
else {
nam_w = col_c - nam_u->str_c + 1;
nam_u->nam_c = malloc(nam_w);
nam_u->nam_c = c3_malloc(nam_w);
uv_strlcpy(nam_u->nam_c, nam_u->str_c, nam_w);
nam_u->por_c = strdup(col_c + 1);
}
@ -120,7 +120,7 @@ u2_raft_readopt(const c3_c* arg_c, c3_c* our_c, c3_s oup_s)
c3_c* end_c;
c3_w por_w = strtoul(nam_u->por_c, &end_c, 10);
if ( '\0' == *nam_u->por_c || '\0' != *end_c || por_w > 65536 ) {
if ( '\0' == *nam_u->por_c || '\0' != *end_c || por_w >= 65536 ) {
uL(fprintf(uH, "raft: invalid port %s\n", nam_u->por_c));
_raft_rnam_free(nam_u);
_raft_rnam_free(nex_u);
@ -143,7 +143,7 @@ u2_raft_readopt(const c3_c* arg_c, c3_c* our_c, c3_s oup_s)
static uv_buf_t
_raft_alloc(uv_handle_t* had_u, size_t siz_i)
{
uv_buf_t buf_u = { .base = malloc(siz_i), .len = siz_i };
uv_buf_t buf_u = { .base = c3_malloc(siz_i), .len = siz_i };
return buf_u;
}
@ -497,7 +497,7 @@ _raft_rmsg_read(const u2_rbuf* buf_u, u2_rmsg* msg_u)
uL(fprintf(uH, "raft: length too short (e) %llu\n", msg_u->len_d));
return -1;
}
msg_u->rest.nam_c = malloc(4 * msg_u->rest.nam_w);
msg_u->rest.nam_c = c3_malloc(4 * msg_u->rest.nam_w);
uv_strlcpy(msg_u->rest.nam_c, (const char*)(buf_u->buf_y + red_i),
4 * msg_u->rest.nam_w);
red_i += 4 * msg_u->rest.nam_w;
@ -539,7 +539,7 @@ _raft_rmsg_read(const u2_rbuf* buf_u, u2_rmsg* msg_u)
red_i = -1;
goto fail;
}
ent_u[i_d].bob_w = malloc(4 * ent_u[i_d].len_w);
ent_u[i_d].bob_w = c3_malloc(4 * ent_u[i_d].len_w);
memcpy(ent_u[i_d].bob_w, buf_u->buf_y + red_i, 4 * ent_u[i_d].len_w);
red_i += 4 * ent_u[i_d].len_w;
}
@ -567,7 +567,7 @@ static u2_rbuf*
_raft_rbuf_grow(u2_rbuf* buf_u, const c3_y* buf_y, size_t siz_i)
{
if ( 0 == buf_u ) {
buf_u = malloc(sizeof(*buf_u) + siz_i);
buf_u = c3_malloc(sizeof(*buf_u) + siz_i);
buf_u->len_w = 0;
buf_u->cap_w = siz_i;
}
@ -751,10 +751,10 @@ _raft_conn_work(u2_rcon* ron_u)
if ( ron_u->wri_u && ron_u->wri_u->len_w > 0 ) {
uv_buf_t buf_u;
struct _u2_write_t* req_u = malloc(sizeof(*req_u));
struct _u2_write_t* req_u = c3_malloc(sizeof(*req_u));
req_u->buf_y = malloc(ron_u->wri_u->len_w);
req_u->buf_y = c3_malloc(ron_u->wri_u->len_w);
memcpy(req_u->buf_y, ron_u->wri_u->buf_y, ron_u->wri_u->len_w);
buf_u.base = (char*)req_u->buf_y;
buf_u.len = ron_u->wri_u->len_w;
@ -816,7 +816,7 @@ _raft_conn_read_cb(uv_stream_t* tcp_u,
static u2_rcon*
_raft_conn_new(u2_raft* raf_u)
{
u2_rcon* ron_u = malloc(sizeof(*ron_u));
u2_rcon* ron_u = c3_malloc(sizeof(*ron_u));
uv_tcp_init(u2L, &ron_u->wax_u);
ron_u->red_u = 0;
@ -863,9 +863,9 @@ _raft_remove_run(u2_rcon* ron_u)
static u2_rreq*
_raft_rreq_new(u2_rcon* ron_u)
{
u2_rreq* req_u = malloc(sizeof(*req_u));
u2_rreq* req_u = c3_malloc(sizeof(*req_u));
req_u->msg_u = malloc(sizeof(*req_u->msg_u));
req_u->msg_u = c3_malloc(sizeof(*req_u->msg_u));
req_u->nex_u = 0;
req_u->ron_u = ron_u;
if ( ron_u->tou_u ) {
@ -1030,7 +1030,7 @@ _raft_getaddrinfo_cb(uv_getaddrinfo_t* raq_u,
struct addrinfo* add_u)
{
struct addrinfo* res_u;
uv_connect_t* con_u = malloc(sizeof(*con_u));
uv_connect_t* con_u = c3_malloc(sizeof(*con_u));
u2_rcon* ron_u = raq_u->data;
//uL(fprintf(uH, "getaddrinfo_cb %s\n", ron_u->nam_u->nam_c));
@ -1077,7 +1077,7 @@ _raft_conn_all(u2_raft* raf_u, void (*con_f)(u2_rcon* ron_u))
while ( nam_u ) {
if ( 0 == nam_u->ron_u || u2_no == nam_u->ron_u->liv ) {
struct addrinfo hit_u;
uv_getaddrinfo_t* raq_u = malloc(sizeof(*raq_u));
uv_getaddrinfo_t* raq_u = c3_malloc(sizeof(*raq_u));
ron_u = _raft_conn_new(raf_u);
@ -1338,7 +1338,7 @@ _raft_foll_init(u2_raft* raf_u)
c3_i wri_i, siz_i;
siz_i = strlen(u2_Host.ops_u.nam_c) + strlen(":65536") + 1;
raf_u->str_c = malloc(siz_i);
raf_u->str_c = c3_malloc(siz_i);
wri_i = snprintf(raf_u->str_c, siz_i, "%s:%d",
u2_Host.ops_u.nam_c, u2_Host.ops_u.rop_s);
c3_assert(wri_i < siz_i);
@ -1357,7 +1357,7 @@ _raft_foll_init(u2_raft* raf_u)
}
if ( (ret_i = u2_sist_has("vote")) >= 0 ) {
c3_assert(ret_i > 0);
vog_c = malloc(ret_i);
vog_c = c3_malloc(ret_i);
u2_sist_get("vote", (c3_y*)vog_c);
uL(fprintf(uH, "raft: vote from sist: %s\n", vog_c));
}
@ -1742,7 +1742,7 @@ u2_raft_work(u2_reck* rec_u)
u2z(ova); ova = nex;
if ( u2_nul != ovo ) {
egg_u = malloc(sizeof(*egg_u));
egg_u = c3_malloc(sizeof(*egg_u));
egg_u->nex_u = 0;
egg_u->cit = u2_no;
egg_u->did = u2_no;
@ -1753,7 +1753,7 @@ u2_raft_work(u2_reck* rec_u)
ron = u2_dc("en:crya", u2k(rec_u->key), ron);
len_w = u2_cr_met(5, ron);
bob_w = malloc(len_w * 4L);
bob_w = c3_malloc(len_w * 4L);
u2_cr_words(0, len_w, bob_w, ron);
u2z(ron);

View File

@ -326,7 +326,7 @@ _sist_cask(u2_reck* rec_u, c3_c* dir_c, u2_bean nun)
}
}
else {
c3_c* say_c = malloc(strlen(paw_c) + 2);
c3_c* say_c = c3_malloc(strlen(paw_c) + 2);
u2_noun say;
say_c[0] = '~';
@ -659,7 +659,7 @@ _sist_rest_nuu(u2_ulog* lug_u, u2_uled led_u, c3_c* old_c)
u2_lo_bail(u2A);
}
img_w = malloc(4 * lar_u.len_w);
img_w = c3_malloc(4 * lar_u.len_w);
end_d = (tar_d - (c3_d)lar_u.len_w);
if ( -1 == lseek64(fid_i, 4ULL * end_d, SEEK_SET) ) {
@ -727,7 +727,7 @@ _sist_rest_nuu(u2_ulog* lug_u, u2_uled led_u, c3_c* old_c)
u2_cr_mug_both(u2_cr_mug(0),
u2_cr_mug(c3__ov)));
img_w = malloc(lar_u.len_w << 2);
img_w = c3_malloc(lar_u.len_w << 2);
u2_cr_words(0, lar_u.len_w, img_w, ovo);
u2z(ovo);
@ -948,7 +948,7 @@ _sist_rest(u2_reck* rec_u)
continue;
}
img_w = malloc(4 * lar_u.len_w);
img_w = c3_malloc(4 * lar_u.len_w);
if ( -1 == lseek64(fid_i, 4ULL * end_d, SEEK_SET) ) {
uL(fprintf(uH, "record (%s) is corrupt (h)\n", ful_c));
@ -1019,14 +1019,18 @@ _sist_rest(u2_reck* rec_u)
u2_reck_wind(rec_u, u2k(now));
if ( (u2_yes == u2_Host.ops_u.vno) &&
(c3__veer == u2h(u2t(ovo))) ) {
uL(fprintf(uH, "replay: skipped veer\n"));
fprintf(stderr, "replay: skipped veer\n");
}
else if ( u2_yes == u2_Host.ops_u.fog &&
u2_nul == t_roe ) {
fprintf(stderr, "replay: -Xwtf, skipped last event\n");
}
else {
_sist_sing(rec_u, u2k(ovo));
fputc('.', stderr);
}
fputc('.', stderr);
// uL(fprintf(uH, "playback: sing: %d\n", xno_w));
// fprintf(stderr, "playback: sing: %d\n", xno_w));
roe = t_roe;
xno_w++;

View File

@ -36,7 +36,7 @@ static void _term_it_do_writes(u2_utty*);
static uv_buf_t
_term_alloc(uv_handle_t* had_u, size_t len_i)
{
return uv_buf_init(malloc(len_i), len_i);
return uv_buf_init(c3_malloc(len_i), len_i);
}
#endif
@ -45,7 +45,7 @@ _term_alloc(uv_handle_t* had_u, size_t len_i)
void
u2_term_io_init()
{
u2_utty* uty_u = malloc(sizeof(u2_utty));
u2_utty* uty_u = c3_malloc(sizeof(u2_utty));
if ( u2_yes == u2_Host.ops_u.dem ) {
uty_u->fid_i = 1;
@ -272,7 +272,7 @@ _term_it_clip(u2_ubuf* buf_u, c3_i siz_i)
static u2_ubuf*
_term_it_buf(c3_w len_w, const c3_y* hun_y)
{
u2_ubuf* buf_u = malloc(len_w + sizeof(*buf_u));
u2_ubuf* buf_u = c3_malloc(len_w + sizeof(*buf_u));
buf_u->len_w = len_w;
memcpy(buf_u->hun_y, hun_y, len_w);
@ -308,7 +308,7 @@ _term_write_cb(uv_write_t* wri_u, c3_i sas_i)
static void
_term_it_write_buf(u2_utty* uty_u, uv_buf_t buf_u)
{
_u2_write_t* ruq_u = (_u2_write_t*) malloc(sizeof(_u2_write_t));
_u2_write_t* ruq_u = (_u2_write_t*) c3_malloc(sizeof(_u2_write_t));
ruq_u->buf_y = (c3_y*)buf_u.base;
@ -342,7 +342,7 @@ _term_it_write_old(u2_utty* uty_u,
// XX extra copy here due to old code. Use hbod as base directly.
//
{
c3_y* buf_y = malloc(old_u->len_w);
c3_y* buf_y = c3_malloc(old_u->len_w);
memcpy(buf_y, old_u->hun_y, old_u->len_w);
buf_u = uv_buf_init((c3_c*)buf_y, old_u->len_w);
@ -532,7 +532,7 @@ _term_it_path(u2_bean fyl, u2_noun pax)
// cut
//
pas_c = malloc(len_w + 1);
pas_c = c3_malloc(len_w + 1);
strncpy(pas_c, u2_Host.cpu_c, len_w);
pas_c[len_w] = '\0';
{
@ -1004,7 +1004,7 @@ _term_ef_blit(u2_utty* uty_u,
case c3__lin: {
u2_noun lin = u2t(blt);
c3_w len_w = u2_ckb_lent(u2k(lin));
c3_w* lin_w = malloc(4 * len_w);
c3_w* lin_w = c3_malloc(4 * len_w);
{
c3_w i_w;

View File

@ -29,7 +29,7 @@ _unix_down(c3_c* pax_c, c3_c* sub_c)
{
c3_w pax_w = strlen(pax_c);
c3_w sub_w = strlen(sub_c);
c3_c* don_c = malloc(pax_w + strlen(sub_c) + 2);
c3_c* don_c = c3_malloc(pax_w + strlen(sub_c) + 2);
strncpy(don_c, pax_c, pax_w + 1);
don_c[pax_w] = '/';
@ -231,7 +231,7 @@ _unix_file_form(u2_udir* dir_u,
c3_w pre_w = strlen(pre_c);
c3_w ext_w = strlen(ext_c);
c3_w ket_w = (u2_yes == ket) ? 1 : 0;
c3_c* pax_c = malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
c3_c* pax_c = c3_malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
strncpy(pax_c, dir_u->pax_c, pax_w);
pax_c[pax_w] = '/';
@ -276,7 +276,7 @@ _unix_dir_forge(u2_udir* dir_u, u2_udir* par_u, u2_noun tet)
c3_c* tet_c = u2_cr_string(tet);
c3_w pax_w = strlen(par_u->pax_c);
c3_w tet_w = strlen(tet_c);
c3_c* pax_c = malloc(pax_w + 1 + tet_w + 1);
c3_c* pax_c = c3_malloc(pax_w + 1 + tet_w + 1);
strncpy(pax_c, par_u->pax_c, pax_w + 1);
pax_c[pax_w] = '/';
@ -504,7 +504,7 @@ _unix_dir_update(u2_udir* dir_u, DIR* rid_u)
}
}
if ( !fil_u ) {
fil_u = malloc(sizeof(u2_ufil));
fil_u = c3_malloc(sizeof(u2_ufil));
// uL(fprintf(uH, "found file %s\n", pax_c));
_unix_file_watch(fil_u, dir_u, pax_c, mod_mp);
@ -524,7 +524,7 @@ _unix_dir_update(u2_udir* dir_u, DIR* rid_u)
}
if ( !dis_u ) {
DIR* red_u = _unix_opendir(pax_c);
dis_u = malloc(sizeof(u2_udir));
dis_u = c3_malloc(sizeof(u2_udir));
// uL(fprintf(uH, "found directory %s\n", pax_c));
_unix_dir_watch(dis_u, dir_u, pax_c);
@ -562,7 +562,7 @@ _unix_load(c3_c* pax_c)
return 0;
}
fln_w = buf_u.st_size;
pad_y = malloc(buf_u.st_size);
pad_y = c3_malloc(buf_u.st_size);
red_w = read(fid_i, pad_y, fln_w);
close(fid_i);
@ -595,7 +595,7 @@ _unix_save(c3_c* pax_c, u2_atom oat)
}
fln_w = u2_met(3, oat);
oat_y = malloc(fln_w);
oat_y = c3_malloc(fln_w);
u2_cr_bytes(0, fln_w, oat_y, oat);
u2z(oat);
@ -846,7 +846,7 @@ _unix_hot_gain(u2_noun who, u2_bean mek)
u2_unix_acquire(pax_c);
{
u2_uhot* hot_u = malloc(sizeof(u2_uhot));
u2_uhot* hot_u = c3_malloc(sizeof(u2_uhot));
_unix_dir_watch(&hot_u->dir_u, 0, pax_c);
@ -987,7 +987,7 @@ _unix_desk_sync_tofu(u2_udir* dir_u,
mpz_t mod_mp;
u2_cr_mp(mod_mp, u2A->now);
*fil_u = malloc(sizeof(u2_ufil));
*fil_u = c3_malloc(sizeof(u2_ufil));
_unix_file_watch(*fil_u, dir_u, pax_c, mod_mp);
mpz_clear(mod_mp);
@ -1019,7 +1019,7 @@ _unix_desk_sync_tako(u2_udir* dir_u, u2_noun pax, u2_noun mis)
u2_udir** dis_u = _unix_pdir(dir_u, u2k(i_pax));
if ( !*dis_u ) {
*dis_u = malloc(sizeof(u2_udir));
*dis_u = c3_malloc(sizeof(u2_udir));
_unix_dir_forge(*dis_u, dir_u, u2k(i_pax));
}
@ -1061,7 +1061,7 @@ _unix_desk_sync_ergo(u2_noun hox,
#endif
if ( !*dir_u ) {
*dir_u = malloc(sizeof(u2_udir));
*dir_u = c3_malloc(sizeof(u2_udir));
xun = u2nt(0, u2_nul, u2_nul);
_unix_dir_forge(*dir_u, &(hot_u->dir_u), u2k(syd));
@ -1279,7 +1279,7 @@ u2_unix_io_init(void)
{
u2_usig* sig_u;
sig_u = malloc(sizeof(u2_usig));
sig_u = c3_malloc(sizeof(u2_usig));
uv_signal_init(u2L, &sig_u->sil_u);
sig_u->num_i = SIGTERM;
@ -1289,7 +1289,7 @@ u2_unix_io_init(void)
{
u2_usig* sig_u;
sig_u = malloc(sizeof(u2_usig));
sig_u = c3_malloc(sizeof(u2_usig));
uv_signal_init(u2L, &sig_u->sil_u);
sig_u->num_i = SIGINT;
@ -1299,7 +1299,7 @@ u2_unix_io_init(void)
{
u2_usig* sig_u;
sig_u = malloc(sizeof(u2_usig));
sig_u = c3_malloc(sizeof(u2_usig));
uv_signal_init(u2L, &sig_u->sil_u);
sig_u->num_i = SIGWINCH;

View File

@ -59,7 +59,7 @@ u2_walk_safe(c3_c* pas_c)
return 0;
}
fln_w = buf_b.st_size;
pad_y = malloc(buf_b.st_size);
pad_y = c3_malloc(buf_b.st_size);
red_w = read(fid_i, pad_y, fln_w);
close(fid_i);
@ -91,7 +91,7 @@ u2_walk_load(c3_c* pas_c)
return u2_cm_bail(c3__fail);
}
fln_w = buf_b.st_size;
pad_y = malloc(buf_b.st_size);
pad_y = c3_malloc(buf_b.st_size);
red_w = read(fid_i, pad_y, fln_w);
close(fid_i);
@ -123,7 +123,7 @@ u2_walk_save(c3_c* pas_c, u2_noun tim, u2_atom pad)
}
fln_w = u2_met(3, pad);
pad_y = malloc(fln_w);
pad_y = c3_malloc(fln_w);
u2_cr_bytes(0, fln_w, pad_y, pad);
u2z(pad);
@ -178,7 +178,7 @@ _walk_in(u2_reck* rec_u, const c3_c* dir_c, c3_w len_w)
else {
c3_c* fil_c = out_n->d_name;
c3_w lef_w = len_w + 1 + strlen(fil_c);
c3_c* pat_c = malloc(lef_w + 1);
c3_c* pat_c = c3_malloc(lef_w + 1);
struct stat buf_b;
strncpy(pat_c, dir_c, lef_w);
@ -277,7 +277,7 @@ u2_path(u2_bean fyl, u2_noun pax)
// cut
//
pas_c = malloc(len_w + 1);
pas_c = c3_malloc(len_w + 1);
strncpy(pas_c, u2_Local, len_w);
pas_c[len_w] = '\0';
{