ObjFW  Check-in [95fdb174f6]

Overview
Comment:Always release the pool in -[OFStreamObserver observe].

Per convention, this would not be necessasry. However, a common
use case is to call -[observe] in a loop that never ends, thus
no pool below the one created in -[observe] will ever be released.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 95fdb174f633295c4c82be56c8f2a9e5c68b099bec4f684719d2d0ffc2b63612
User & Date: js on 2011-10-25 00:02:22
Other Links: manifest | tags
Context
2011-10-28
18:02
Fix a missing import. check-in: 3626a9162c user: js tags: trunk
2011-10-25
00:02
Always release the pool in -[OFStreamObserver observe]. check-in: 95fdb174f6 user: js tags: trunk
2011-10-24
18:28
Don't retain delegates to prevent reference cycles. check-in: 87cd99ff88 user: js tags: trunk
Changes

Modified src/OFStreamObserver_kqueue.m from [fea66ded56] to [b5282d84cd].

93
94
95
96
97
98
99

100
101
102
103
104
105
106

107

108
109
110
111
112
113
114
115

116
117

118
119
120
121
122
123
124
125
126

127

128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146
147

148
149
150
151


152
153
154
155



156
157
158
159

	EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
	[changeList addItem: &event];
}

- (BOOL)observeWithTimeout: (int)timeout
{

	struct timespec timespec = { timeout, 0 };
	struct kevent eventList[EVENTLIST_SIZE];
	int i, events;

	[self _processQueue];

	if ([self _processCache])

		return YES;


	events = kevent(kernelQueue, [changeList cArray],
	    (int)[changeList count], eventList, EVENTLIST_SIZE,
	    (timeout == -1 ? NULL : &timespec));

	if (events == -1) {
		switch (errno) {
		case EINTR:

			return NO;
		case ENOMEM:

			@throw [OFOutOfMemoryException exceptionWithClass: isa];
		default:
			assert(0);
		}
	}

	[changeList removeNItems: [changeList count]];

	if (events == 0)

		return NO;


	for (i = 0; i < events; i++) {
		if (eventList[i].ident == cancelFD[0]) {
			char buffer;

			assert(read(cancelFD[0], &buffer, 1) > 0);

			continue;
		}

		if (eventList[i].flags & EV_ERROR) {
			[delegate streamDidReceiveException:
			    FDToStream[eventList[i].ident]];

			continue;
		}

		switch (eventList[i].filter) {
		case EVFILT_READ:
			[delegate streamIsReadyForReading:
			    FDToStream[eventList[i].ident]];

			break;
		case EVFILT_WRITE:
			[delegate streamIsReadyForWriting:
			    FDToStream[eventList[i].ident]];


		default:
			assert(0);
		}
	}




	return YES;
}
@end







>






|
>

>








>


>








|
>

>













>







>




>
>



|
>
>
>




93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

	EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
	[changeList addItem: &event];
}

- (BOOL)observeWithTimeout: (int)timeout
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	struct timespec timespec = { timeout, 0 };
	struct kevent eventList[EVENTLIST_SIZE];
	int i, events;

	[self _processQueue];

	if ([self _processCache]) {
		[pool release];
		return YES;
	}

	events = kevent(kernelQueue, [changeList cArray],
	    (int)[changeList count], eventList, EVENTLIST_SIZE,
	    (timeout == -1 ? NULL : &timespec));

	if (events == -1) {
		switch (errno) {
		case EINTR:
			[pool release];
			return NO;
		case ENOMEM:
			[pool release];
			@throw [OFOutOfMemoryException exceptionWithClass: isa];
		default:
			assert(0);
		}
	}

	[changeList removeNItems: [changeList count]];

	if (events == 0) {
		[pool release];
		return NO;
	}

	for (i = 0; i < events; i++) {
		if (eventList[i].ident == cancelFD[0]) {
			char buffer;

			assert(read(cancelFD[0], &buffer, 1) > 0);

			continue;
		}

		if (eventList[i].flags & EV_ERROR) {
			[delegate streamDidReceiveException:
			    FDToStream[eventList[i].ident]];
			[pool releaseObjects];
			continue;
		}

		switch (eventList[i].filter) {
		case EVFILT_READ:
			[delegate streamIsReadyForReading:
			    FDToStream[eventList[i].ident]];
			[pool releaseObjects];
			break;
		case EVFILT_WRITE:
			[delegate streamIsReadyForWriting:
			    FDToStream[eventList[i].ident]];
			[pool releaseObjects];
			break;
		default:
			assert(0);
		}

	}

	[pool release];

	return YES;
}
@end

Modified src/OFStreamObserver_poll.m from [032c6d7a87] to [c610bddecc].

123
124
125
126
127
128
129
130

131

132
133
134
135
136
137
138
139
140
141

142

143
144
145
146
147
148
149
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	struct pollfd *FDsCArray;
	size_t i, nFDs;

	[self _processQueue];

	if ([self _processCache])

		return YES;


	FDsCArray = [FDs cArray];
	nFDs = [FDs count];

#ifdef OPEN_MAX
	if (nFDs > OPEN_MAX)
		@throw [OFOutOfRangeException exceptionWithClass: isa];
#endif

	if (poll(FDsCArray, (nfds_t)nFDs, timeout) < 1)

		return NO;


	for (i = 0; i < nFDs; i++) {
		if (FDsCArray[i].revents & POLLIN) {
			if (FDsCArray[i].fd == cancelFD[0]) {
				char buffer;

				assert(read(cancelFD[0], &buffer, 1) > 0);







|
>

>









|
>

>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
{
	OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
	struct pollfd *FDsCArray;
	size_t i, nFDs;

	[self _processQueue];

	if ([self _processCache]) {
		[pool release];
		return YES;
	}

	FDsCArray = [FDs cArray];
	nFDs = [FDs count];

#ifdef OPEN_MAX
	if (nFDs > OPEN_MAX)
		@throw [OFOutOfRangeException exceptionWithClass: isa];
#endif

	if (poll(FDsCArray, (nfds_t)nFDs, timeout) < 1) {
		[pool release];
		return NO;
	}

	for (i = 0; i < nFDs; i++) {
		if (FDsCArray[i].revents & POLLIN) {
			if (FDsCArray[i].fd == cancelFD[0]) {
				char buffer;

				assert(read(cancelFD[0], &buffer, 1) > 0);

Modified src/OFStreamObserver_select.m from [d0c40db2e0] to [85d5b1242b].

76
77
78
79
80
81
82
83

84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101

102
103
104
105
106
107
108
	fd_set writeFDs_;
	fd_set exceptFDs_;
	struct timeval time;
	size_t i, count;

	[self _processQueue];

	if ([self _processCache])

		return YES;


#ifdef FD_COPY
	FD_COPY(&readFDs, &readFDs_);
	FD_COPY(&writeFDs, &writeFDs_);
	FD_COPY(&exceptFDs, &exceptFDs_);
#else
	readFDs_ = readFDs;
	writeFDs_ = writeFDs;
	exceptFDs_ = exceptFDs;
#endif

	time.tv_sec = timeout / 1000;
	time.tv_usec = (timeout % 1000) * 1000;

	if (select((int)maxFD + 1, &readFDs_, &writeFDs_, &exceptFDs_,
	    (timeout != -1 ? &time : NULL)) < 1)

		return NO;


	if (FD_ISSET(cancelFD[0], &readFDs_)) {
		char buffer;
#ifndef _WIN32
		assert(read(cancelFD[0], &buffer, 1) > 0);
#else
		assert(recvfrom(cancelFD[0], &buffer, 1, 0, NULL, NULL) > 0);







|
>

>















|
>

>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
	fd_set writeFDs_;
	fd_set exceptFDs_;
	struct timeval time;
	size_t i, count;

	[self _processQueue];

	if ([self _processCache]) {
		[pool release];
		return YES;
	}

#ifdef FD_COPY
	FD_COPY(&readFDs, &readFDs_);
	FD_COPY(&writeFDs, &writeFDs_);
	FD_COPY(&exceptFDs, &exceptFDs_);
#else
	readFDs_ = readFDs;
	writeFDs_ = writeFDs;
	exceptFDs_ = exceptFDs;
#endif

	time.tv_sec = timeout / 1000;
	time.tv_usec = (timeout % 1000) * 1000;

	if (select((int)maxFD + 1, &readFDs_, &writeFDs_, &exceptFDs_,
	    (timeout != -1 ? &time : NULL)) < 1) {
		[pool release];
		return NO;
	}

	if (FD_ISSET(cancelFD[0], &readFDs_)) {
		char buffer;
#ifndef _WIN32
		assert(read(cancelFD[0], &buffer, 1) > 0);
#else
		assert(recvfrom(cancelFD[0], &buffer, 1, 0, NULL, NULL) > 0);